一,监听对象的操作

1,使用defineProperty监听对象操作

  • 1,Object.defineProperty设计的初衷不是监听截止对象中所有属性的,在定义某些属性的时候初衷只是定义普通的属性,但是后面强行被添加数据属性描述符。
  • 2,Object.defineProperty属性无法监听删除属性、添加属性等操作。

2,Proxy

在ES6中,新增了一个Proxy类,这个类从名字就可以看出来,是用于帮助我们创建一个代理的:

  • 也就是说,如果我们希望监听一个对象的相关操作,那么我们可以先创建一个代理对象(Proxy对象);
  • 之后对该对象的所有操作,都通过代理对象来完成,代理对象可以监听我们想要对原对象进行哪些操作;
  • target:目标对象(侦听的对象);
  • property:将被设置的属性key;
  • value:新属性值;

- receiver:调用的代理对象;

get函数有三个参数:

  • target:目标对象(侦听的对象);
  • property:被获取的属性key;
  • receiver:调用的代理对象;

Proxy所有捕获器:13个

  • handler.getPrototypeOf():Object.getPrototypeOf 方法的捕捉器。
  • handler.setPrototypeOf():Object.setPrototypeOf 方法的捕捉器。
  • handler.isExtensible():Object.isExtensible 方法的捕捉器。
  • handler.preventExtensions():Object.preventExtensions 方法的捕捉器。
  • handler.getOwnPropertyDescriptor():Object.getOwnPropertyDescriptor 方法的捕捉器。
  • handler.defineProperty():Object.defineProperty 方法的捕捉器。
  • handler.ownKeys():Object.getOwnPropertyNames 方法和Object.getOwnPropertySymbols 方法的捕捉器。
  • handler.has():in 操作符的捕捉器。
  • handler.get():属性读取操作的捕捉器。
  • handler.set():属性设置操作的捕捉器。
  • handler.deleteProperty():delete 操作符的捕捉器。
  • handler.apply():函数调用操作的捕捉器。
  • handler.construct():new 操作符的捕捉器。

Proxy的construct和applyconstruct和apply是应用于函数对象的

  • 比如Reflect.getPrototypeOf(target)类似于Object.getPrototypeOf();
  • 比如Reflect.defineProperty(target, propertyKey, attributes)类似于Object.defineProperty() ;

如果我们有Object可以做这些操作,那么为什么还需要有Reflect这样的新增对象呢? 这是因为在早期的ECMA规范中没有考虑到这种对对象本身的操作如何设计会更加规范,所以将这些API放到了Object上面;但是Object作为一个构造函数,这些操作实际上放到它身上并不合适;另外还包含一些类似于in、delete操作符,让JS看起来是会有一些奇怪的;

所以在ES6中新增了Reflect,让我们这些操作都集中到了Reflect对象上;

Reflect的常见方法和Proxy是一一对应的,也是13个

Reflect的使用

4,Receiver的作用

我们发现在使用getter、setter的时候有一个receiver的参数,如果我们的源对象(obj)有setter、getter的访问器属性,那么可以通过receiver来改变里面的this;