这是面试的第三家公司了 = = 砥砺前行好吧。
说实话,笔试题手写代码真的难受 = =,面试的时候还不问我实现思路和答案(那我笔试的意义何在),面谈最后还是三句灵魂拷问:
- 你觉得你自己做前端有什么优势?
- 你觉得你最有成就感的项目是?印象最深刻的项目是?
话不多说了,直接上题吧!
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;
- margin: 10px; // 外边距离全是 10px
- margin: 10px 20px; // 上下外边距 10px,左右外边距 20px
- margin: 10px 20px 30px;// 上外边距 10px,左右外边距 20px,下边距是 30px
- 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)
}
答案:
- 在极短的一段时间内输出 5,随后每隔一秒输出一个 5
// 5 5 5 5 5
- 在极短的一段时间内输出 0,随后每隔一秒结果加 1
// 0 1 2 3 4
- 在极短的一段时间内输出 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}
我的答案不一定是正确且优秀的,解析可能也有写不充分的地方,欢迎大家留言指正或补充