从vue3 源码重新认识数组的 indexOf, lastIndexOf, includes

4,083 阅读2分钟

问题的来源

阅读 vue3 的源码时,看到了下面的这段代码:

const arrayInstrumentations: Record = {} 
;['includes', 'indexOf', 'lastIndexOf'].forEach(key => { 
  arrayInstrumentations[key] = function(...args): any {
    const arr = toRaw(this) as any
    for (let i = 0, l = (this as any).length; i < l; i++) {
      track(arr, TrackOpTypes.GET, i + '')
    }
    const res = arr[key](...args)
    if (res === -1 || res === false) {
      return arr[key](...args.map(toRaw))
    } else {
      return res
    }
  }
})

为了做依赖的收集,vue3 对这个三个数组的方法进行了一层包装,刚看的时候百思不得其解。因为在使用这三个方法时,同样会遍历数据,这样子做包装的意义在哪呢?思索了良久不得其解,重新刷了这三个方法后才恍然大悟。下面先让我自己重新认识这三个方法,然后再对上面的代码进行分析。

重新认识

indexOf 和 lastIndexOf

这两个 api 唯一的区别就是查找方向不同。其余都一样。它们的参数如下:

参数 描述
searchvalue 必须,表示要搜索的值
fromindex 可选的整数参数。规定在字符串中开始检索的位置。它的合法取值是 0 到 stringObject.length - 1。如省略该参数,则将从字符串的首字符开始检索。

它们都有第二个参数,表示搜索的开始位置,并且不能为负值。

includes

参数如下:

参数 描述
searchvalue 必须,表示要搜索的值
fromindex 可选。从该索引处开始查找 searchElement。如果为负值,则按升序从 array.length + fromIndex 的索引开始搜索。默认为 0。

分析

它们三个由于第二个参数的存在,可能不会从数组的第一个元素开始遍历。这导致的问题是当数组的某一项发生变化时不会响应式的重新执行这三个 api,(这里暗含的就是第二个参数可能是会变动的)所以 vue3 就包装了这三个方法,在执行这三个方法时就去将其注册到每一项的依赖中去,这样子保证了不论在什么情况下都会在响应式数组更新项时去更新依赖。

小菜鸡的总结

平时使用时第二个参数几乎是不会用的,导致渐渐的遗忘了,在此做一个记录。