1

这是面试的第三家公司了= =砥砺前行好吧。

说实话,笔试题手写代码真的难受 = =,面试的时候还不问我实现思路和答案(那我笔试的意义何在),面谈最后还是三句灵魂拷问:

  • 你觉得你自己做前端有什么优势?
  • 你觉得你最有成就感的项目是?印象最深刻的项目是?

话不多说了,直接上题吧!

1、对于一个宽度固定但是高度不固定的元素,如何实现水平居中和垂直居中?

html 文档

<div class="parent">
    <div class="child"></div>
</div>
  • flex实现

.parent{
  display: flex;
  justify-content:center;
  align-items:center;
  height:100px;
  border: 1px solid red;
}
.child {
  width:  100px;
  border: 1px solid red;
}
  • position实现

margin常见的几种写法
默认值:margin: 0;
  1. margin: 10px; // 外边距离全是10px
  2. margin: 10px 20px; // 上下外边距10px,左右外边距20px
  3. margin: 10px 20px 30px;// 上外边距10px,左右外边距20px,下边距是30px
  4. margin: 10px 20px 30px 40px; // 从左往右依次外边距方向依次是上、右、下、左
.parent{
  height:100px;
  border: 1px solid red;
  position: relative;
}
.child {
  position: absolute;
  width: 100px;
  top: 50%;
  left:50%;
  transform: translate(-50%,-50%);
}
这里有个小提问:为什么设置margin:auto;水平会居中,但是垂直却不居中呢?不是说auto是自动计算属性?

2、下面三段代码分别输出什么?并且什么时候输出什么?

for (var i = 0; i < 5; i++) {
  setTimeout(function () {
    console.log(i)
  }, 1000 * i)
} 
for (let i = 0; i < 5; i++) {
  setTimeout(function () {
    console.log(i)
  }, 1000 * i)
} 
for (var i = 0; i < 5; i++) {
    (function (i) {
      setTimeout(function () {
        console.log(i)
      }, 1000 * i)
    })(i)
} 

答案:

  1. 在极短的一段时间内输出5,随后每隔一秒输出一个5

// 5 5 5 5 5

  1. 在极短的一段时间内输出0,随后每隔一秒结果加1

// 0 1 2 3 4

  1. 在极短的一段时间内输出0,随后每隔一秒结果加1

// 0 1 2 3 4

解析:
1.首先要明白js的事件循环机制,for循环结束后才到宏观任务setTimeout,这时候i的值已经变为5了
2.let i 是块作用域,类似于

for (let i = 0; i < 5; i++) {
  let i = /* 块作用域里面的i */
  setTimeout(function () {
    console.log(i)
  }, 1000 * i)
}

因此每一次循环,i的值都是块作用域里面的值
3.立即执行函数,创建了属于自己的作用域,因此每一次执行都是不同的i

3、下面这段代码输出了什么?

var a = 1;
var obj = {
  a: 2,
  func1: () => {
    console.log(this.a);
  },
  func2: function () {
    console.log(this.a);
  }
}

var obj2 = { a: 3 };

console.log(obj.func1());
console.log(obj.func2());

obj.func2.apply(obj2);

var newFunc = obj.func2;

newFunc();

答案:

var a = 1;
var obj = {
  a: 2,
  // 注意箭头函数的this指向是在定义的时候就绑定了而不是在执行的时候,因此func1的this指向一个空对象
  func1: () => {
    console.log(this.a);
  },
  func2: function () {
    console.log(this.a);
  }
}

var obj2 = { a: 3 };

console.log(obj.func1()); // 函数是没返回值的,首先会打印undefined,函数体里面是箭头函数this指向undefined,因此还会打印出undefined
console.log(obj.func2());// 函数是没返回值的,首先会打印undefined,函数体里面是普通匿名函数this指向obj,因此还会打印出2

obj.func2.apply(obj2);
// 显式更改this的指向到obj2,因此打印3

var newFunc = obj.func2;

newFunc();
// 在全局环境下调用func2函数,此时this指向全局变量window,打印1

4、实现一个函数:输入一个整数,求该整数的二进制表达中有多少个1?

我的答案:

// 十进制转化二进制--除2取余法
function toBinary(number) {
  let arr = []
  while (number > 0) {
    let a = number % 2
    number = (number - a) / 2
    arr.push(a)
  }
  return arr.reverse()
}
// 筛选出含有1的数组
// 一次遍历 时间复杂度是N
let a = toBinary(1223).filter(item=>item === 1)
console.log(a.length) // 获得多少个1个数

网上还有一些利用补码等解决的方式

5、实现一个函数:给定一个字符串,找出出现次数最多的字符。

我的答案:

// 暴力的2次循环,复杂度n^2
function getMostChart(str) {
  let list = [...str]; // 拆分字符串为数组
  let noRepeatList = Array.from(new Set(list)) // 合并数组中重复的元素
  let lengthList  = [] // noRepeatList每一项在list出现的次数组成的数组
  noRepeatList.map(ele => {
    let count = 0;
    list.map(item => {
      if (ele === item) {
        count++
      }
    })
    lengthList.push(count) // [ 1, 1, 2, 1, 1 ]
  })
 let max = lengthList[0]
  // 获取最大值及其下标
  for (let i = 0; i < lengthList.length; i++) {
    let current = lengthList[i];
    current > max ? max = current : null
  }
  
  // 注意这里maxIndex可能不止一个,最好还是for循环获取最大值的下标
  let maxIndex = lengthList.findIndex(item => item === max)
  
  return noRepeatList[maxIndex]
}

getMostChart('choose') // o
我的答案不够优秀并且忽略了次数出现最多的字符可能会有多个
,比如说'ccoo'

网上利用JSON特性,时间复杂度只有N的答案

6、实现一个单向链表类,要求支持新增、删除、查找操作

答案

/**
* 定义一个节点类
*/
class Node {
  constructor(val) {
    this.val = val; // 结点值
    this.next = null; // 结点指针,指向下一项
  }
}

/**
* 定义一个单向链表类
*/

class LinkedList {
  constructor() {
    this.headNode = new Node('head'); // 初始化一个头结点
  }
    
  // 新增节点
  insert(val) {
    let currentNode = this.headNode,
        lastNode = new Node(val);
    
    while(true) {
      if(currentNode.next == null) {
        break;
      } else {
        currentNode = currentNode.next;
      }
    }
    
    lastNode.next = currentNode.next;
    currentNode.next = lastNode;
  }
    
  
    
  // 删除链表某一项
  remove(val) {
    let currentNode = this.headNode;
    
    while(true) {
      if(currentNode.next.val == val) {
        break;
      } else {
        currentNode = currentNode.next;
      }
    }
    
    currentNode.next = currentNode.next.next;
  }
  
  // 查找
  search(val) {
    let currentNode = this.headNode;
    while (currentNode.next) {
          currentNode = currentNode.next;
          if (currentNode.val === val) {
            return currentNode
          }
        }
      }
  }
}


var nodes = new LinkedList();

nodes.insert('a');
nodes.insert('b');
nodes.insert('c');
console.log(nodes.search('c')); // Node { val: 'orange', next: null }
我的答案不一定是正确且优秀的,解析可能也有写不充分的地方,欢迎大家留言指正或补充

李文武
41 声望3 粉丝

我曾经失落失望,失掉所有方向