前端面试100题

1、介绍一下 npm 模块安装机制,为什么输入 npm install 就可以自动安装对应的模块?

当我们输入 npm install 的时候,虽然没有在后面加模块名,它会自动去 package.json 中去寻找,我们之前安装过的 依赖项,然后把这些依赖项安装。


2 、连等赋值

输出一下代码的执行结果,并解释为什么

1
2
3
4
5
6
var a = {n: 1};
var b = a;
a.x = a = {n: 2};

console.log(a.x) //undefined
console.log(b.x) //{n:2}

这道题考的就是我们对连等赋值的理解。

连等开始之前,程序会把所有引用都保存下来,连等的过程中,这些值是不变的,等到连等都完事了,再一块变

我们来看一下这个图:

① a 指向 了{n:1}

② b 等于 a ,则b的内存也指向了 {n:1}

③ 这是连等赋值,连等开始之前,程序会把所有引用都保存下来,连等的过程中,这些值是不变的,等到连等都完事了,再一块变,程序从右往左,先看a = {n:2} 也就是如图的③.1 ,a 指向了 {n:2},

但是由于是连等赋值,此时 a 还是保持这对 {n:1} 的引用。然后再看 a.x = a 也就是如图的 ③.2 , 在a引用的内存地址中 添加一个 x 属性,并赋值为 {n:2}。再然后 如图③.3 等到整个语句完成后,a不再指向{n:1},而指向了 {n:2}。

所以最后的结果变成了
a=={n: 2};
console.log(a.x) => undefined //因为a没有x属性

b=={n: 1, x: {n: 2}}
console.log(b.x) => {n: 2}


另一种解释:

1.首先,这个问题最关键的是连等赋值本身的行为,用最简单的话说。连等,会让所有变量都变成最右边的值,这是基础。

a=b=c=value

2.那么问题来了——这句话,到底计算机是怎么理解的
a.x = a = {n: 2};

3.这里的重点是a.x到底是谁

简单来说,在赋值过程开始时,a其实是{n:1}

a.x=a={n:2}
其实在计算机眼中是长成这样的:
{n:1}.x=a={n:2}

4.所以,这个赋值发生了两件事

//1.把”a”变成了{n:2}
//2.把{n:1}的x变成了{n:2}——————–

也就是说:
a.x = a = {n: 2};
其实被计算机执行成了
{n:1}.x={n: 2};
a={n: 2};

所以最后的结果变成了
a=={n: 2};
console.log(a.x) => undefined //因为a没有x属性

b=={n: 1, x: {n: 2}}
console.log(b.x) => {n: 2}



3、数组里面有10万个数据,取第一个元素和第10万个元素的事件相差多少?

回答: 完全一样

解释: 数组是随机访问的。数组在内存中是一段连续内存空间,实际上你只要知道首地址和偏移量,首地址就是Arrary本身,偏移量就是下标。两者一相加就是我们要找的位置。实际上数组的寻址操作是一样的,无论是加1也好还是加1000000也罢,cup计算加法是完全一样的。


4、使用 sort() 对数组 [3,15,8,29,102,22] 进行排序,输出结果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
   let arr = [3, 15, 8, 29, 102, 22]

//方法一
arr.sort(function(n1, n2) {
if (n1 > n2) {
return 1
} else if (n1 < n2) {
return -1
} else {
return 0
}
})
//方法二,简便写法
arr.sort((n1, n2) => n1 - n2)
console.log(arr); //[3, 8, 15, 22, 29, 102]

5 、实现一个 sleep 函数 比如 sleep(1000) 意味着 等待1000毫秒,可以从Promist、Generator、Async/Await 等角度实现。

1
2
3
4
5
6
7
8
9
10
11
function sleep(ms){
return new Promise(resolve=>{
setTimeout(resolve,ms);
});
}

(async ()=>{
console.log(111)
await sleep(2000)
console.log(222) //两秒之后出现222
})();

6、 (携程)算法手写题 已知如下数组:编写一个程序,将数组扁平化去除其中的重复数据,最终得到一个升序且不重复的数组。

let arr = [

[1, 2, 2],

[3, 4, 5, 5],

[6, 7, 8, 9, [11, 12, [12, 13, [14]]], 10]

]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
let arr = [
[1, 2, 2],
[3, 4, 5, 5],
[6, 7, 8, 9, [11, 12, [12, 13, [14]]], 10]
]
let result = []
let json = {}

flat(arr);
// 扁平化+去重
function flat(arr) {
for (let i = 0; i < arr.length; i++) {
if (typeof arr[i] == 'number') { //去重
if (!json[arr[i]]) {
result.push(arr[i]);
json[arr[i]] = true;
}
} else {
flat(arr[i]);
}
}
}
// 排序1
result.sort((n1, n2) => n1 - n2)
// 手写排序
for (let i = 1; i < result.length; i++) {
for (let j = i; j > 0; j--) {
if (result[j] < result[j - 1]) {
let tmp = result[j];
result[j] = result[j - 1];
result[j - 1] = tmp
}
}
}

console.log(result); //[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]

7、(滴滴,饿了么)写React / Vue 项目时为什么要在列表组件中写key ,其作用是什么?

传送门

一、vue中列表循环需加 :key=”唯一标识” 唯一标识可以是item里面id index等,因为vue组件高度复用增加Key可以标识组件的唯一性,为了更好的区别各个组件 key的作用主要是为了高效的更新虚拟DOM 。

二、避免一些奇怪的问题,当我们数据比较复杂的时候,如果不加key,可能会出现一条数据被渲染了两次,或者我们已经删除某数据,但是该数据的节点还在。

三、比如我们在做动画的时候,需要进行强制刷新,我们会更改key值,这样它就会认为我的数据已经改了,就会进行刷新。





持续更新中。。。