前端面试每日3+2(第42天)

1/13/2020 前端100问

当你发现自己的才华撑不起你的野心时,就请安静下来学习吧!

鲁迅说过:答案仅供参考...

# 1、第 76 题:输出以下代码运行结果

// example 1
var a={}, b='123', c=123;  
a[b]='b';
a[c]='c';  
console.log(a[b]); 

---------------------
// example 2
var a={}, b=Symbol('123'), c=Symbol('123');  
a[b]='b';
a[c]='c';   
console.log(a[b]); 

---------------------
// example 3
var a={}, b={key:'123'}, c={key:'456'};  
a[b]='b';
a[c]='c';  
console.log(a[b]);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

🌿【解析】🌿
这题考察的是对象的键名的转换。

  • 对象的键名只能是字符串和 Symbol 类型。
  • 其他类型的键名会被转换成字符串类型。
  • 对象转字符串默认会调用 toString 方法。
// example 1
var a={}, b='123', c=123;
a[b]='b';

// c 的键名会被转换成字符串'123',这里会把 b 覆盖掉。
a[c]='c'; 
// 输出 c
console.log(a[b]);
1
2
3
4
5
6
7
8
// example 2
var a={}, b=Symbol('123'), c=Symbol('123');  

// b 是 Symbol 类型,不需要转换。
a[b]='b';

// c 是 Symbol 类型,不需要转换。任何一个 Symbol 类型的值都是不相等的,所以不会覆盖掉 b。
a[c]='c';

// 输出 b
console.log(a[b]);
1
2
3
4
5
6
7
8
9
10
11
// example 3
var a={}, b={key:'123'}, c={key:'456'};  

// b 不是字符串也不是 Symbol 类型,需要转换成字符串。
// 对象类型会调用 toString 方法转换成字符串 [object Object]。
a[b]='b';

// c 不是字符串也不是 Symbol 类型,需要转换成字符串。
// 对象类型会调用 toString 方法转换成字符串 [object Object]。这里会把 b 覆盖掉。
a[c]='c';  

// 输出 c
console.log(a[b]);
1
2
3
4
5
6
7
8
9
10
11
12
13

参考答案 (opens new window) --- 感谢【Daily-Interview-Question】 (opens new window)

# 2、第 77 题:算法题「旋转数组」

给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。

示例 1:

输入: [1, 2, 3, 4, 5, 6, 7] 和 k = 3
输出: [5, 6, 7, 1, 2, 3, 4]
解释:
向右旋转 1 : [7, 1, 2, 3, 4, 5, 6]
向右旋转 2 : [6, 7, 1, 2, 3, 4, 5]
向右旋转 3 : [5, 6, 7, 1, 2, 3, 4]
1
2
3
4
5
6

示例 2:

输入: [-1, -100, 3, 99] 和 k = 2
输出: [3, 99, -1, -100]
解释: 
向右旋转 1 : [99, -1, -100, 3]
向右旋转 2 : [3, 99, -1, -100]
1
2
3
4
5

🌿【解析】🌿

function rotate(arr, k) {
  const len = arr.length
  const step = k % len // 因为步数有可能大于数组长度,所以要先取余
  return arr.slice(-step).concat(arr.slice(0, len - step))
}
// rotate([1, 2, 3, 4, 5, 6], 7) => [6, 1, 2, 3, 4, 5]
1
2
3
4
5
6

参考答案 (opens new window) --- 感谢【Daily-Interview-Question】 (opens new window)

# 3、第 78 题:Vue 的父组件和子组件生命周期钩子执行顺序是什么


🌿【解析】🌿

  • 加载过程:
    父beforeCreate => 父created => 父beforeMount => 子beforeCreate => 子created => 子beforeMount => 子mounted => 父mounted
  • 子组件更新过程:
    父beforeUpdate => 子beforeUpdate => 子updated => 父updated
  • 父组件更新过程:
    父beforeUpdate => 父updated
  • 销毁过程:
    父beforeDestroy => 子beforeDestroy => 子destroyed => 父destroyed

参考答案 (opens new window) --- 感谢【Daily-Interview-Question】 (opens new window)

# 4、第 79 题:input 搜索如何防抖,如何处理中文输入


🌿【解析】🌿
简易防抖:

<div>
    <input type="text" id="ipt">
</div>
<script>
    let ipt = document.getElementById('ipt');
    let dbFun = debounce()
    ipt.addEventListener('keyup', function (e) {
        dbFun(e.target.value);
    })
    function debounce() {
        let timer;
        return function (value) {
            clearTimeout(timer);
            timer = setTimeout(() => {
            console.log(value)
            }, 500);
        }
    }
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

中文输入问题,其实看过elementui框架源码的童鞋都应该知道,elementui是通过compositionstart & compositionend做的中文输入处理: 相关代码:

<input
    ref="input"
    @compositionstart="handleComposition"
    @compositionupdate="handleComposition"
    @compositionend="handleComposition"
>
1
2
3
4
5
6

这3个方法是原生的方法,这里简单介绍下,官方定义如下compositionstart 事件触发于一段文字的输入之前(类似于 keydown 事件,但是该事件仅在若干可见字符的输入之前,而这些可见字符的输入可能需要一连串的键盘操作、语音识别或者点击输入法的备选词) 简单来说就是切换中文输入法时在打拼音时(此时input内还没有填入真正的内容),会首先触发compositionstart,然后每打一个拼音字母,触发compositionupdate,最后将输入好的中文填入input中时触发compositionend。触发compositionstart时,文本框会填入 “虚拟文本”(待确认文本),同时触发input事件;在触发compositionend时,就是填入实际内容后(已确认文本),所以这里如果不想触发input事件的话就得设置一个bool变量来控制。

输入到input框触发input事件 失去焦点后内容有改变触发change事件 识别到你开始使用中文输入法触发**compositionstart 事件 未输入结束但还在输入中触发compositionupdate **事件 输入完成(也就是我们回车或者选择了对应的文字插入到输入框的时刻)触发compositionend事件。

那么问题来了 使用这几个事件能做什么? 因为input组件常常跟form表单一起出现,需要做表单验证

为了解决中文输入法输入内容时还没将中文插入到输入框就验证的问题

我们希望中文输入完成以后才验证

解决oninput事件在中文输入法下会取得拼音的值的问题 (opens new window)

参考答案 (opens new window) --- 感谢【Daily-Interview-Question】 (opens new window)

# 5、第 80 题:介绍下 Promise.all 使用、原理实现及错误处理


🌿【解析】🌿

all(list) {
    return new Promise((resolve, reject) => {
        let resValues = [];
        let counts = 0;
        for (let [i, p] of list) {
            resolve(p).then(res => {
                counts++;
                resValues[i] = res;
                if (counts === list.length) {
                    resolve(resValues)
                }
            }, err => {
                reject(err)
            })
        }
    })
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

参考答案 (opens new window) --- 感谢【Daily-Interview-Question】 (opens new window)

Last Updated: 1/29/2020, 9:58:38 PM
    asphyxia
    逆时针向