# 前端面试题及答案汇总(四) 41-50
# 第 41 题:下面代码输出什么
var a = 10;
(function () {
console.log(a)
a = 5
console.log(window.a)
var a = 20;
console.log(a)
})()
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
- undefined
- 10
- 20
# 第 42 题:实现一个 sleep 函数
promise
function sleep(time) {
return new Promise((resolve, reject) => {
setTimeout(resolve, time);
})
}
sleep(1000).then(() => console.log(1));
1
2
3
4
5
6
2
3
4
5
6
async
function sleep(time) {
return new Promise(resolve => setTimeout(resolve, time))
}
async function sleepAsync(time) {
console.log(1111);
await sleep(time);
console.log(222);
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
Generator
function *sleep(time) {
yield new Promise((resolve) => {
setTimeout(resolve, time);
})
}
sleep(1000).next()
1
2
3
4
5
6
2
3
4
5
6
es5
function sleep(callback, time) {
if (typeof callback === 'function') {
setTimeout(callback, time);
}
}
function output() {
console.log(111);
}
sleep(output, 1000);
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# 第 43 题:使用 sort() 对数组 [3, 15, 8, 29, 102, 22] 进行排序,输出结果
102 15 22 29 3 8
默认的排序方法会将数组元素转换为字符串,然后比较字符串中字符的UTF-16编码顺序来进行排序。
# 第 44 题:介绍 HTTPS 握手过程
- 浏览器 发送随机数 random1 + 支持的加密算法列表 到服务器
- 服务器 发送随机数 random2 + 选择的加密算法 + 数字证书(公钥在证书里) + 确认信息
- 浏览器 验证证书有效性
- 浏览器 生成一个随机数 pre-master,采用非对称加密通过服务器的公钥加密发送给服务器,同时根据加密算法将 random1 + random2 + pre-master 生成 master-secret 用于后续数据传输
- 服务器 用私钥解密得到 pre-master,根据算法将 random1 + random2 + pre-master 生成 master-secret用于数据传输
- 对称加密,浏览器和服务器之间使用 master-secret 加密的数据进行通信
# 第 45 题:HTTPS 握手过程中,客户端如何验证证书的合法性
- 首先浏览器读取证书中的证书所有者、有效期等信息进行校验,校验证书的网站域名是否与证书颁发的域名一致,校验证书是否在有效期内
- 浏览器开始查找操作系统中已内置的受信任的证书发布机构CA,与服务器发来的证书中的颁发者CA比对,用于校验证书是否为合法机构颁发,但是这个 CA 可能比较小众,浏览器不知道该不该信任它,然后浏览器会继续查找给这个 CA 颁发证书的 CA,再以同样的方式验证它上级 CA 的可靠性。
- 如果找不到,浏览器就会报错,说明服务器发来的证书是不可信任的。
- 如果找到,那么浏览器就会从操作系统中取出颁发者CA 的公钥(多数浏览器开发商发布版本时,会事先在内部植入常用认证机关的公开密钥),然后对服务器发来的证书里面的签名进行解密
- 浏览器使用相同的hash算法计算出服务器发来的证书的hash值,将这个计算的hash值与证书中签名做对比
- 对比结果一致,则证明服务器发来的证书合法,没有被冒充
# 第 46 题:输出以下代码执行的结果并解释为什么
var obj = {
'2': 3,
'3': 4,
'length': 2,
'splice': Array.prototype.splice,
'push': Array.prototype.push
}
obj.push(1)
obj.push(2)
console.log(obj)
// [empty × 2, 1, 2, splice: ƒ, push: ƒ]
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
类数组:
- 对象上有splice,且splice是一个函数;
- 对象上含有length属性,且是个数字;
满足上面两个要求就是类数组
push 方法根据 length 属性来决定从哪里开始插入给定的值。 push 是特意设计为通用的,Array.prototype.push 可以在一个对象上工作。
- 满足要求所以输出是个类数组
- push是从length开始的,所以从2开始,即类数组的前两位是空,所以自动补上empty
- obj.push(1) -> obj[2] = 1
- obj.push(2) -> obj[3] = 2
- 输出 [empty × 2, 1, 2, splice: ƒ, push: ƒ]
# 第 47 题:双向绑定和 vuex 是否冲突
# 第 48 题:call 和 apply 的区别是什么,哪个性能更好一些
- Function.prototype.apply和Function.prototype.call 的作用是一样的,区别在于传入参数的不同;
- 第一个参数都是,指定函数体内this的指向;
- 第二个参数开始不同,apply是传入带下标的集合,数组或者类数组,apply把它传给函数作为参数,call从第二个开始传入的参数是不固定的,都会传给函数作为参数。
- call比apply的性能要好,平常可以多用call, call传入参数的格式正是内部所需要的格式,参考call和apply性能对比
# 第 49 题:为什么通常在发送数据埋点请求的时候使用的是 1x1 像素的透明 gif 图片?
- 能够完成整个 HTTP 请求+响应(尽管不需要响应内容)
- 触发 GET 请求之后不需要获取和处理数据、服务器也不需要发送数据
- 跨域友好
- 执行过程无阻塞
- 相比 XMLHttpRequest 对象发送 GET 请求,性能上更好
- GIF的最低合法体积最小(最小的BMP文件需要74个字节,PNG需要67个字节,而合法的GIF,只需要43个字节)
# 第 50 题:(百度)实现 (5).add(3).minus(2) 功能。
Number.prototype.add = function(n) {
if (typeof n !== 'number') {
throw new Error('请输入数字');
}
return this + n;
}
Number.prototype.minus = function(n) {
if (typeof n !== 'number') {
throw new Error('请输入数字');
}
return this - n;
}
console.log((5).add(3).minus(2))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15