vue2为什么只重写了7个数组方法

发布时间 2023-11-17 15:57:12作者: 柯基与佩奇

首先看源码

//即将要被劫持的数组
let arr = [1, 2, 3];

//先把要劫持的方法列出来
let methods = ["push", "pop", "shift", "unshift", "reverse", "sort", "splice"];

//既然要劫持原型,就要先把原型拿过来
let arrayProto = Array.prototype;
//创建一个自己的原型方法
let arrayMethods = Object.create(Array.prototype);

//遍历方法
methods.forEach((method) => {
  //给每个方法做切片
  arrayMethods[method] = function (...args) {
    //还是先调用真正的原型方法获得正常的返回值
    const result = arrayProto[method].apply(this, args);
    //模拟插入切片
    console.log(`调用了${method}方法`);

    return result;
  };
});
arr.__proto__ = arrayMethods;
// 数组重写
const originalProto = Array.prototype;
const arrayProto = Object.create(originalProto)[
  ("push", "pop", "shift", "unshift", "splice", "reverse", "sort")
].forEach((method) => {
  arrayProto[method] = function () {
    originalProto[method].apply(this.arguments);
    dep.notice();
  };
});

// set、delete
Vue.set(obj, "bar", "newbar");
Vue.delete(obj, "bar");

确实只有 7 个方法被重写,至于为什么是 7 个,观察了一下特征,这 7 个方法都是能改变数组本身的方法,也只有这个数组本身改变需要检测才需要去重新通知。接着去 MDN 查了下,能改变数组本身分方法的还有以下这两个方法

Array.prototype.fill();
Array.prototype.copyWithin();

那为什么 vue 没有重写这两个方法呢,后来想了下,vue2 出生的早,这两个方法 es6 出生的晚,那时候还不兼容这两个方法,现在 vue2 给一个数组用 fill 方法,不就监听不到变化?于是用代码试了下

data() {
  return {
    arr: [1, 2, 4]
  }
}
test() {
  this.arr.fill(0, 0, 2);
},
<el-button @click="test"></el-button>
<div v-for="(item, i) in arr" :key="i">{{ item }}</div>

点了没反应,数组不会重新渲染。

结论:vue2 是旧时代的产物了,能上 3 就上 3 吧,3 里面这种问题就不复存在。