# 前端面试题及答案汇总(九) 91-100
# 第 91 题:介绍下 HTTPS 中间人攻击
https 协议由 http + ssl 协议构成,具体的链接过程可参考 SSL 或 TLS 握手的概述
中间人攻击过程如下:
- 服务器向客户端发送公钥。
- 攻击者截获公钥,保留在自己手上。
- 然后攻击者自己生成一个【伪造的】公钥,发给客户端。
- 客户端收到伪造的公钥后,生成加密 hash 值发给服务器。
- 攻击者获得加密 hash 值,用自己的私钥解密获得真秘钥。
- 同时生成假的加密 hash 值,发给服务器。
- 服务器用私钥解密获得假秘钥。 -服务器用加秘钥加密传输信息
防范方法:
服务端在发送浏览器的公钥中加入 CA 证书,浏览器可以验证 CA 证书的有效性
# 第 92 题:已知数据格式,实现一个函数 fn 找出链条中所有的父级 id
let list = [
{
id: "1",
children: [
{
id: "11",
children: [
{
id: "111"
},
{
id: "112"
}
]
}
]
}
];
function fn(value) {
// 回溯的标记
let _p = Symbol("parent");
// 找到子节点
let result;
function _fn(arr, p) {
for (let i = 0; i < arr.length; i++) {
arr[i][_p] = p;
if (arr[i].id === value) {
result = arr[i];
return;
}
!result && arr[i].children && _fn(arr[i].children, arr[i]);
}
if (result) return;
}
_fn(list, null);
let tmp = [];
if (!result) return null;
while (result) {
tmp.unshift(result.id);
result = result[_p];
}
return tmp;
}
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
37
38
39
40
41
42
43
44
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
37
38
39
40
41
42
43
44
# 第 93 题:给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。请找出这两个有序数组的中位数。要求算法的时间复杂度为 O(log(m+n))。
/**
* @param {number[]} nums1
* @param {number[]} nums2
* @return {number}
*/
var findMedianSortedArrays = function(nums1, nums2) {
if (nums1.length > nums2.length) [nums1, nums2] = [nums2, nums1];
const length1 = nums1.length;
const length2 = nums2.length;
let min = 0;
let max = length1;
let half = Math.floor((length1 + length2 + 1) / 2);
while (max >= min) {
const i = Math.floor((max + min) / 2);
const j = half - i;
if (i > min && nums1[i - 1] > nums2[j]) {
max = i - 1;
} else if (i < max && nums1[i] < nums2[j - 1]) {
min = i + 1;
} else {
let left, right;
if (i === 0) left = nums2[j - 1];
else if (j === 0) left = nums1[i - 1];
else left = Math.max(nums1[i - 1], nums2[j - 1]);
if (i === length1) right = nums2[j];
else if (j === length2) right = nums1[i];
else right = Math.min(nums1[i], nums2[j]);
return (length1 + length2) % 2 ? left : (left + right) / 2;
}
}
return 0;
};
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
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
# 第 94 题:vue 在 v-for 时给每项元素绑定事件需要用事件代理吗?为什么?
# 第 95 题:模拟实现一个深拷贝,并考虑对象相互引用以及 Symbol 拷贝的情况
# 第 96 题:介绍下前端加密的常见场景和方法
# 第 97 题:React 和 Vue 的 diff 时间复杂度从 O(n^3) 优化到 O(n) ,那么 O(n^3) 和 O(n) 是如何计算出来的?
# 第 98 题:(京东)写出如下代码的打印结果
function changeObjProperty(o) {
o.siteUrl = "http://www.baidu.com";
o = new Object();
o.siteUrl = "http://www.google.com";
}
let webSite = new Object();
changeObjProperty(webSite);
console.log(webSite.siteUrl);
// http://www.baidu.com
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 第 99 题:(bilibili)编程算法题
function fun(num) {
let num1 = num / 10;
let num2 = num % 10;
if (num1 < 1) {
return num;
} else {
num1 = Math.floor(num1);
}
return `${num2}${fun(num1)}`;
}
var a = fun(12345);
console.log(a);
console.log(typeof a);
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
# 第 100 题:(京东)请写出如下代码的打印结果
function Foo() {
Foo.a = function() {
console.log(1);
};
this.a = function() {
console.log(2);
};
}
// 以上只是 Foo 的构建方法,没有产生实例,此刻也没有执行
Foo.prototype.a = function() {
console.log(3);
};
// 现在在 Foo 上挂载了原型方法 a ,方法输出值为 3
Foo.a = function() {
console.log(4);
};
// 现在在 Foo 上挂载了直接方法 a ,输出值为 4
Foo.a();
// 立刻执行了 Foo 上的 a 方法,也就是刚刚定义的,所以
// # 输出 4
let obj = new Foo();
/* 这里调用了 Foo 的构建方法。Foo 的构建方法主要做了两件事:
1. 将全局的 Foo 上的直接方法 a 替换为一个输出 1 的方法。
2. 在新对象上挂载直接方法 a ,输出值为 2。
*/
obj.a();
// 因为有直接方法 a ,不需要去访问原型链,所以使用的是构建方法里所定义的 this.a,
// # 输出 2
Foo.a();
// 构建方法里已经替换了全局 Foo 上的 a 方法,所以
// # 输出 1
// 4 2 1
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
37
38
39
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
37
38
39