proxy

双向数据绑定3


使用defineProperty能实现数据层的双向绑定,优点是兼容性较高,属于es5的特性,缺点是数据劫持无法监听深层的数据变化,明显的是数据的变化需要额外的逻辑判断并且只能劫持对象属性,如果属性值也是对象,则需要遍历深层,显然能劫持一个完整的对象是我们想要的

所以就有了第二种方式实现双向数据绑定--Proxy(代理)

Proxy 用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种“元编程”(meta programming),即对编程语言进行编程。Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。

同defineProperty一样,Proxy也是通过set和get是想双向数据绑定

[set] && [get]

get(target, key, reciver)

// target: 目标对象
// key: 目标属性
// reciver: proxy实例本身
var person = {
  name: "张三"
};

var proxy = new Proxy(person, {
  get: function(target, property) {
    if (property in target) {
      return target[property];
    } else {
      throw new ReferenceError("Property \"" + property + "\" does not exist.");
    }
  }
});
proxy.name // "张三"
proxy.age // 抛出一个错误

set(target, key, value, reciver)

// target: 目标对象
// key: 目标属性
// value: 属性值
// reciver: proxy实例本身
let validator = {
  set: function(obj, prop, value) {
    if (prop === 'age') {
      if (!Number.isInteger(value)) {
        throw new TypeError('The age is not an integer');
      }
      if (value > 200) {
        throw new RangeError('The age seems invalid');
      }
    }

    // 对于满足条件的 age 属性以及其他属性,直接保存
    obj[prop] = value;
  }
};

let person = new Proxy({}, validator);

person.age = 100;

person.age // 100
person.age = 'young' // 报错
person.age = 300 // 报错

优点

  • proxy可以劫持整个对象而非一个属性
  • proxy可以直接监听数组的变化
  • proxy的支持方法比defineProperty多

缺点

  • Proxy的劣势就是兼容性问题,而且无法用polyfill磨平

你可能感兴趣的:(proxy)