整个面试过程还是挺舒适的,回答得还可以,就记录一下几个回答得不是很好的问题吧:
vue2的批量更新
即缓存数据的变更(如果有相同的更新要做合并操作),异步进行视图的更新(通过vue.nextTick()
实现)。
缓存数据变更
ini
let queue = []; // 使用数组缓存变更的 watcher
let has = {}; // watcher id的收集,用于查重
let pending = false; // 标志位
function collectQueueWatcher(watcher) {
let id = watcher.id;
if (has[id] == null) {
has[id] = true;
queue.push(watcher);
if (!pending) {
nextTick(flushschedulerQueue); // 异步任务,在它执行前,同步代码可以往 缓存队列queue 中继续添加watcher
pending = true;
}
}
}
function flushSchedulerQueue() {
queue.forEach(watcher => watcher.update());
queue = [];
has = {};
pending = false;
}
异步更新
任何异步操作都是基于js的事件循环机制的,即在同步代码执行的过程中把任务入栈到 微任务队列 或者 宏任务队列。在这里我们使用Promise
来创建微任务,实现异步操作。
javascript
// nextTick的简单实现,使用Promise
function nextTick (fn) {
return Promise.resolve().then(fn);
}
nextTick优化
上面的这个nextTick
的简单实现对于视图更新来说已经够用了,毕竟视图更新本身就已经有缓存队列来实现批量操作,那么如果是用户手动调用nextTick
呢?按照这个简单实现,我们得创造许多个微任务。所以,我们可以在这里也使用一个缓存队列来减少微任务的创建,优化丐版nextTick
ini
let nextQueue = [];
let pending = false;
function nextTick (fn) {
fnQueue.push(fn);
if (!pending) {
Promise.resolve().then(flushNextQueue);
pending = true;
}
}
function flushNextQueue() {
nextQueue.forEach(fn => fn());
nextQueue = [];
pending = false;
}
PS: 这里使用forEach
还是很关键的,它能记住开始执行时的array
的状态,即使循环过程中这个array
有新增也不会造成影响。
对比vue2diff,vue3的优化
大概看了一些详细文章,vue3中新增了静态优化比较,即对于被标记的静态节点直接拿来复用。
【后续再深入看下代码来补充这一part】
Map和Set
Map
Map相当于是普通键值对象的改良
- 普通对象中,键名会转化为
string
类型,Map允许任何类型的键值 - 提供查询时O(1)复杂度的优化
使用
go
const map = new Map(); // 创建Map类型的数据
map.set('name', '王五');
map.get('name'); // 取值
map.has('name'); // 查询
map.delete('name'); // 删除
map.clear(); // 清空所有键值对
map.size(); // 返回键值对的数量
查询需求比较频繁的时候用它(相当于 用空间换时间)。
Set
集合,Set相当于数组的改良
- Set中的元素是唯一的,不重复
- 增删查都很快O(1)
- 不能通过索引来访问
- 常用forEach或者for..of来遍历
使用
csharp
const set = new Set(array);
set.add(1); // 添加元素
set.has(1); // 是否有该元素
set.delete(1); // 删除元素
set.clear(); // 清空元素
set.size(); // 元素数量
一般用于数组去重
WeakMap和WeakSet
WeakMap和Map、WeakSet和Set之间的区别都在于弱引用和强引用,Weak前缀的都是弱引用。
- WeakMap的键值是弱引用,即垃圾回收不会因为WeakMap的关系而不对无效键值进行回收处理
- WeakSet中的元素只能是
Object
和Symbol
类型 - WeakSet可以实现自动清理回收,实际上也是弱引用的关系,垃圾回收不会因为WeakMap的关系而不对元素进行回收处理
ES6+新特性
这个内容可以讲很多,所以这里列举一些常用的:
let
,const
,块级作用域,避免了var
的变量提升带来的各种麻烦- 箭头函数
() => {}
,相比于function
函数最重要的变化是this
取决于声明时而不是运行时 - 模板字符串,拼接字符很爽
- 解构赋值,
const {name, age} = user
async/await
- 展开预算符
...
Proxy
,vue3响应式改进的核心,比object.definProperty
好使Promise
,异步的神