Object.defineProperty 与 Proxy

众所周知,Vue2.0 的双向数据绑定原理是基于 数据劫持 和 发布订阅,数据劫持部分用的就是Object.defineProperty();但是Vue 3.0 已经做出优化,改为 Proxy() 代理的方式。

1.优缺点比较

  • Object.defineProperty():将一个js对象传递给vue实例对象的data()时,vue通过Object.defineProperty来遍历目标对象内部的属性。
    • 优点: 更为准确
    • 缺点:无法对数据下标进行监控,需要遍历对象,效率低
  • Proxy代理:将传入对象,及对象内部全部改为Proxy代理的方式。
    • 优点:可以监听整个对象,不必遍历,当然数组也可以。
    • 缺点:兼容性

2.实现的对比

这里借用我上课时老师写的例子 ^_^

先来看看Object.defineProperty怎么玩的。。。

<input type="text" id="textInput">
输入:<span id="textSpan"></span>
var obj = {},
      textInput = document.querySelector("#textInput"), //输入
      textSpan = document.querySelector("#textSpan"); //输出

Object.defineProperty(obj, 'name', {
      get: function () {
            console.log('get');
            return v
      },
      set: function (val) {
            console.log('set');
            v = val
      }
});

textInput.onkeyup = function () {
      obj.name = textInput.value;
      textSpan.innerHTML = obj.name;
}

此时,在输入框键入字符,可以看到get set均会被调用。

如果是数组呢???

var Obj = {}
Object.defineProperty(Obj, 'a', {
      get: function () {
            console.log('get');
            return v
      },
      set: function (val) {
            console.log('set');
            v = val
      }
});
Obj.a = [] // set  设置a为[], 调用set 这里没问题

Obj.a.push('1') // get 这里也是设置a里面的元素啊,为什么会调用get???

Obj.a[0] = 1 // get ??? why

Obj.a.pop(1) // get ??? why

Obj.a = [1, 2, 3] //  为什么这里又是 set 了呢?

来解释一下上面的结果:

  • Obj.a = []; // 这里对Obj的属性a做出赋值操作,set

  • Obj.a.push('1'); Obj.a.pop(1); // 这些是对属性a的内部进行操作,Object.defineProperty就不行了。

  • Obj.a = [1, 2, 3];// 这里对属性a的整体进行了赋值操作,set

总结: 尽管对于Object.defineProperty做了优化处理,但是在监控数组下标时还是有问题。

再来看看Proxy是怎么玩的。。。

var arr = [];
var p = new Proxy(arr, {
      get: (target, key) => {
            console.log('get')
            return key in target ? target[key] : undefined
      },
      set: (target, key, value) => {
            console.log('set')
            target[key] = value
            return true
      }
})
p.push(1);
get // 获取数组arr的push方法
get // 获取数组arr的length属性
set // 设置arr[0] = 1
set // 设置数组arr长度为1

可以看到,p.push(1);  // Proxy对于数组的元素,数组的长度 分别进行了监听。

猜你喜欢

转载自blog.csdn.net/vampire10086/article/details/109637146