代理——Proxy

在ES6中,新增了一个类Proxy,Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。

  • 如果希望监听一个对象的相关操作,那么可以先创建一个代理对象。
  • 之后对该对象的所有操作,都通过代理对象来完成。

    Proxy的基本使用

    语法

    1. const p = new Proxy(target, handler)

    target:要使用 Proxy 包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。 handler:一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理 p 的行为。 如果我们想要侦听某些具体的操作,那么就可以在handler中添加对应的捕捉器(Trap)

Proxy的get和set的捕获

  • set的四个参数
    • target:目标对象
    • property:将被设置的key
    • value:新值
    • receiver: 调用的代理对象
  • get的三个参数
    • target:目标对象
    • property:将被设置的key
    • receiver: 调用的代理对象

实例:

  1. const obj = {
  2. name: "abc",
  3. age: 18,
  4. };
  5. const objProxy = new Proxy(obj, {
  6. get(target, property, receiver) {
  7. console.log("get捕获", property);
  8. return target[property];
  9. },
  10. set(target, property, value, receiver) {
  11. console.log("set捕获", property);
  12. target[property] = value;
  13. },
  14. has(target, p) {
  15. console.log("has捕获", p);
  16. return p in target;
  17. },
  18. deleteProperty(target, p) {
  19. console.log("deleteProperty捕获", p);
  20. delete target[p];
  21. },
  22. });
  23. console.log(objProxy.name);
  24. objProxy.age = 38;
  25. console.log(objProxy);
  26. console.log("height" in objProxy);
  27. delete objProxy["age"];
  28. console.log(objProxy);

image.png

Proxy的所有捕获器

in 操作符的捕捉器。

属性读取操作的捕捉器。

属性设置操作的捕捉器。

delete 操作符的捕捉器。

Object.getPrototypeOf 方法的捕捉器。

Object.setPrototypeOf 方法的捕捉器。

Object.isExtensible 方法的捕捉器。

Object.preventExtensions 方法的捕捉器。

Object.getOwnPropertyDescriptor 方法的捕捉器。

Object.defineProperty 方法的捕捉器。

Object.getOwnPropertyNames 方法和 Object.getOwnPropertySymbols 方法的捕捉器。

函数调用操作的捕捉器。

new 操作符的捕捉器。

Receiver的作用

如果源对象(obj)有setter、getter的访问器属性,那么可以通过receiver来改变里面的this;

反射——Reflect

Reflect 是一个内置的对象,它提供拦截 JavaScript 操作的方法。这些方法与Proxy的方法相同。
Reflect不是一个函数对象,因此它是不可构造的。

Reflect的所有静态方法

所有静态方法与Proxy的所有捕获器相对应。

对一个函数进行调用操作,同时可以传入一个数组作为调用参数。和 Function.prototype.apply() 功能类似。

对构造函数进行 new操作,相当于执行 new target(…args)。

Object.defineProperty() 类似。如果设置成功就会返回 true

作为函数的delete操作符,相当于执行 delete target[name]。

获取对象身上某个属性的值,类似于 target[name]。

类似于 Object.getOwnPropertyDescriptor()。如果对象中存在该属性,则返回对应的属性描述符, 否则返回 undefined.

类似于 Object.getPrototypeOf()

判断一个对象是否存在某个属性,和 in运算符 的功能完全相同。

类似于 Object.isExtensible().

返回一个包含所有自身属性(不包含继承属性)的数组。(类似于 Object.keys(), 但不会受enumerable影响).

类似于 Object.preventExtensions()。返回一个Boolean

将值分配给属性的函数。返回一个Boolean,如果更新成功,则返回true。

设置对象原型的函数. 返回一个 Boolean, 如果更新成功,则返回true。

:::info Reflect主要提供了很多操作JavaScript对象的方法,有点像Object中操作对象的方法;
比如Reflect.getPrototypeOf(target)类似于 Object.getPrototypeOf();
比如Reflect.defineProperty(target, propertyKey, attributes)类似于Object.defineProperty() ;
尽管二者之间存在 某些细微上的差别 . ::: 实例:

  1. const obj = {
  2. name: "abc",
  3. age: 18,
  4. };
  5. const objProxy = new Proxy(obj, {
  6. get(target, property, receiver) {
  7. console.log("get捕获", property);
  8. return Reflect.get(target, property, receiver);
  9. },
  10. set(target, property, value, receiver) {
  11. console.log("set捕获", property);
  12. Reflect.set(target, property, value, receiver)
  13. },
  14. has(target, p) {
  15. console.log("has捕获", p);
  16. return Reflect.has(target, p)
  17. },
  18. deleteProperty(target, p) {
  19. console.log("deleteProperty捕获", p);
  20. Reflect.deleteProperty(target, p)
  21. },
  22. });
  23. console.log(objProxy.name);
  24. objProxy.age = 38;
  25. console.log(objProxy);
  26. console.log("height" in objProxy);
  27. delete objProxy["age"];
  28. console.log(objProxy);

image.png