前端每天10问 —— 1-10
1.Q:写 React / Vue 项目时为什么要在列表组件中写 key,其作用是什么?
更详细的参考资料请移步:
A:不带key时节点能够就地复用,省去了销毁/创建组件的开销,同时只需要修改DOM文本内容而不是移除/添加节点,这就是文档中所说的“刻意依赖默认行为以获取性能上的提升”。但是key的作用是什么呢?
(1)更准确
因为带key就不是就地复用
了,在sameVnode函数 a.key === b.key
对比中可以避免就地复用的情况。所以会更加准确。
(2) 更快
利用key的唯一性生成map对象来获取对应节点,比遍历方式更快。
(3) 保证组件状态正确
使用唯一id作为key
当新旧节点的头头、尾尾、头尾、尾头对比都没有结果时,会根据新节点的key去对比旧节点数组中的key,从而找到相应旧节点(这里对应的是一个key => index 的map映射)。如果没找到就认为是一个新增节点。而如果没有key,那么就会采用遍历查找的方式去找到对应的旧节点。一种一个map映射,另一种是遍历查找。相比而言。map映射的速度更快。
1 | // vue项目 src/core/vdom/patch.js -448行 |
2.Q:[‘1’, ‘2’, ‘3’].map(parseInt) what & why ?
A:[1, NaN, NaN],map函数的第一个参数callback,这个callback一共可以接收三个参数,其中第一个参数代表当前被处理的元素,而第二个参数代表该元素的索引。parseInt则是用来解析字符串的,使字符串成为指定基数的整数。parseInt(string, radix)
接收两个参数,第一个表示被处理的值(字符串),第二个表示为解析时的基数。
解析:
- parseInt(‘1’, 0) //基数为0时,且string参数不以“0x”和“0”开头时,按照10为基数处理。这个时候返回1
- parseInt(‘2’, 1) //基数为1(1进制)表示的数中,最大值小于2,所以无法解析,返回NaN
- parseInt(‘3’, 2) //基数为2(2进制)表示的数中,最大值小于3,所以无法解析,返回NaN
3.Q:什么是防抖和节流?有什么区别?如何实现?
A:
- 防抖
触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间
1 | function debounce(fn,delay){ |
2.节流
隔一段时间,执行一次,所以节流会稀释函数的执行频率。
1 | function throttle(fn,delay){ |
4.Q:介绍下 Set、Map、WeakSet 和 WeakMap 的区别?
A:
- Set
- 成员唯一、无序且不重复
- [value, value],键值与键名是一致的(或者说只有键值,没有键名)
- 可以遍历,方法有:add、delete、has
- WeakSet
- 成员都是对象
- 成员都是弱引用,可以被垃圾回收机制回收,可以用来保存DOM节点,不容易造成内存泄漏
- 不能遍历,方法有add、delete、has
- Map
- 本质上是键值对的集合,类似集合
- 可以遍历,方法很多可以跟各种数据格式转换
- WeakMap
- 只接受对象作为键名(null除外),不接受其他类型的值作为键名
- 键名是弱引用,键值可以是任意的,键名所指向的对象可以被垃圾回收,此时键名是无效的
- 不能遍历,方法有get、set、has、delete
5.Q:介绍下深度优先遍历和广度优先遍历,如何实现?
A:
深度优先遍历:对每一个可能的分支路径深入到不能再深入为止,而且每个结点只能访问一次。
广度优先遍历:又叫层次遍历,从上往下对每一层依次访问,在每一层中,从左往右(也可以从右往左)访问结点,访问完一层就进入下一层,直到没有结点可以访问为止。
1 | //HTML |
6.Q:ES5/ES6 的继承除了写法以外还有什么区别?
A:Class 作为构造函数的语法糖,同时有prototype
属性和__proto__
属性,因此同时存在两条继承链。
(1)子类的__proto__
属性,表示构造函数的继承,总是指向父类。
(2)子类prototype
属性的__proto__
属性,表示方法的继承,总是指向父类的prototype
属性。
1 | //ES6 |
7.Q: 请写出下面代码的运行结果(setTimeout、Promise、Async/Await 的区别)
更详细的资料请移步:
重点:await是一个让出线程的标志。await后面的表达式会先执行一遍,将await后面的代码加入到microtask中,然后就会跳出整个async函数来执行后面的代码。
1 | //原式 |
A:
1 | //原式 |
8. Q:
已知如下数组:
var arr = [ [1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14] ] ] ], 10];
编写一个程序将数组扁平化去并除其中重复部分数据,最终得到一个升序且不重复的数组
A:
1 | function handleArr(arr){ |
9.Q:JS 异步解决方案的发展历程以及优缺点。
A:
10.Q:情人节福利题,如何实现一个 new
A:
1 | function New(){ |