关于Proxy实例里set和definPropety的触发情况

379 阅读1分钟

在阮一峰大神的ES6教程中提到:

Proxy.set拦截里面使用了Reflect.set,而且传入了receiver,导致触发Proxy.defineProperty拦截。这是因为Proxy.setreceiver参数总是指向当前的 Proxy实例(即上例的obj),而Reflect.set一旦传入receiver,就会将属性赋值到receiver上面(即obj),导致触发defineProperty拦截。如果Reflect.set没有传入receiver,那么就不会触发defineProperty拦截。

此时如果在set拦截器中,没有调用Reflect.set方法,或者说没有传入receiver的话,就不会触发defineProperty拦截。 此外,如果在设置proxy实例的拦截器对象时,没有设置set拦截器,只是设置defineProperty拦截器时,通过proxy实例设置目标对象的属性时,会直接触发defineProperty拦截器:

var handler = {
  defineProperty (target, key, descriptor) {
    console.log('start define')
    return false;
  }
};
var target = {};
var proxy = new Proxy(target, handler);
proxy.foo = 'bar'// 'start define'

同时读取 proxy.foo 时,返回 undefined。这表明在没有在拦截器对象中设置set拦截器时,通过proxy对象设置属性值,会通过已经设置的 defineProperty 拦截器,对目标属性进行赋值操作。 而在拦截器对象中只设置set拦截器,未设置defineProperty 拦截器时,通过Object.defineProperty 方法设置属性值时,并不会触发set 拦截器。这表明通过 object.propName 的方式对属性赋值,覆盖了set 拦截器和 defineProperty 拦截器两种,或者说覆盖了对象属性赋值的两种方式;而 Object.defineProperty 方法对属性赋值,并不会涉及到 object.propName/object[propName] 这种赋值方式。