美文网首页
聊聊 Object.defineProperty() 的不足,以

聊聊 Object.defineProperty() 的不足,以

作者: 前端好有趣 | 来源:发表于2021-01-26 15:34 被阅读0次

Object.defineProperty() 的不足

如果有同学对 Object.defineProperty() 还不是很熟悉,建议先看看这篇文章:五分钟快速搞定 Object.defineProperty()

众所周知 Object.defineProperty() 在数组监控方面不足,哪里不足?我们来看下面这个例子:

let data = {
    list: []
}

Object.keys(data).forEach(function (key) {
    let value = data[key];
    Object.defineProperty(data, key, {
        enumerable: true,
        configurable: true,
        get() {
            return value;
        },
        set(newValue) {
            console.log(`Array Changed`);
            value = newValue;
            return true;
        }
    })
})

data.list.push(1);                 //--->  A 行代码
// data.list = [1, 2, 3];          //--->  B 行代码
console.log(data.list);

既然是对数组的监控,那么就该能监测到数组元素的增加或者删除。因此,向 list 中增加元素的时候,理应会有打印 Array Changed

但实际情况是,数组的确发生了改变(增加了一个元素),但并没有打印出 Array Changed,因此并没有检测到数组的变化。只有在 B 行代码被解开之后,控制台才会打印出 Array Changed

因此,我们可以大胆得猜测:当监控数据对象中的 数组 的时候,实质上是监控数组的地址,地址不变也就不会被监测到。所以,我们向 listpush 元素的时候并没有触发打印;当我们直接替换 list 对象的时候就触发了打印。这就是 Object.defineProperty() 在数组监控方面的不足。

那么,如何使 Object.defineProperty() 在弥补先天不足的情况下实现对数组的精准监控。

改进一下 Object.defineProperty 的使用

let arrayMethod = Object.create(Array.prototype);
['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'].forEach(function (method) {
  Object.defineProperty(arrayMethod, method, {
    enumerable: true,
    configurable: true,
    value: function () {
      let args = [...arguments]
      Array.prototype[method].apply(this, args);
      console.log(`operation: ${method}`)
      // 这是 vue 中的代码,目的是监听动作
      dep.notify();
    }
  })
});

上面代码,仅仅是数据中的数组对象的原型被修改掉了,并不会影响到全局的数组对象。

Proxy 的诞生

因为 Object.defineProperty() 在数组监控方面的不足,所以后期发展出了 Proxy(代理)。

一次性搞懂 ES6 的 Proxy 看看,Proxy 如何帮助我们实现数据监控,解决问题。

相关文章

网友评论

      本文标题:聊聊 Object.defineProperty() 的不足,以

      本文链接:https://www.haomeiwen.com/subject/xhnfyktx.html