JS - Principio de captura de proxy y revocación de proxy

El nuevo proxy (Proxy) y la reflexión (Reflect) de ES6 brindan a los desarrolladores la capacidad de interceptar e incorporar comportamientos adicionales en las operaciones básicas. Específicamente, se puede definir un objeto proxy asociado para el objeto de destino, y este objeto proxy se puede usar como The abstract se utiliza el objeto de destino, es decir, antes de realizar varias operaciones en el objeto de destino, estas operaciones se pueden controlar en el objeto proxy

⚠️: Dado que el proxy es una nueva capacidad de lenguaje básico, muchos traductores no pueden convertir el comportamiento del proxy en el código ECMAScript anterior, y el comportamiento del proxy es en realidad irremplazable. En otras palabras, el proxy solo puede ser 100% compatible con su uso en la plataforma

mapas mentales

Agente base

El agente es una abstracción del objeto de destino, que se puede utilizar como sustituto del objeto de destino. Es completamente independiente del objeto de destino. El objeto de destino puede ser operado directamente o a través de un proxy, es decir, cualquier operación realizada por el objeto proxy silly girl en realidad se aplicará al objeto de destino, la única diferencia perceptible es que el objeto proxy se opera en el código, pero el objeto proxy y el objeto de destino no acceden a la misma dirección

const target = {
  id: "id15",
};

const handlder = {};

const proxy = new Proxy(target, handlder);
// 代理对象和目标对象访问的属性是同名的时候,本质访问的就是同一个值,
// 给目标对象 或者代理对象 属性赋值也会反映到两个对象上
log(proxy.id === target.id); // log: true

target.id = "id_15";
log(proxy.id); // log: id_15
log(target.id); // log: id_15

proxy.id = "pro_id";
log(proxy.id); // log: pro_id
log(target.id); // log: pro_id

// Proxy.rototype 是 undefiend,所以不能使用 instanceof 操作符
log(target instanceof Proxy); // TypeError: Function has non-object prototype 'undefined' in instanceof check

receptor

El propósito principal de usar un proxy es personalizar la trampa. Un receptor es un interceptor definido en un objeto controlador. Para cada objeto controlador, se pueden definir cero o más receptores. Cada receptor corresponde a una operación básica, que se puede llamar directa o indirectamente en el objeto proxy. Cada vez que se llama a estas operaciones básicas en el objeto proxy, el proxy puede interceptar y modificar el comportamiento correspondiente llamando a la función catcher antes de que estas operaciones se propaguen al objeto de destino.

Todos los receptores pueden reconstruir la operación original en función de sus propios parámetros, que pueden reconstruirse fácilmente llamando al método del mismo nombre en el objeto Reflect global (encapsulando el comportamiento original), es decir, todos los métodos que pueden capturarse en el controlador el objeto tiene los métodos correspondientes de la API Reflect que tienen el mismo nombre y firma de función que el método interceptado por el capturador, y también se comportan igual que el método interceptado

const proxy = new Proxy(
  { name: "jakequc" },
  {
    // 捕获器在处理程序对象中以方法名为键
    // proxy.property / proxy[property] 等获取属性的时候会出发 get 捕获器
    get(target, key, receiver) {
      // target 是代理的目标对象,key 获取时的 键(属性),receiver 是代理对象
      // log(target, key, receiver);
      return target[key] + "__";
    },
  }
);

log(proxy.name); // log: jakequc__

const reproxy = new Proxy(
  {
    age: 23,
  },
  {
    // 甚至可以写成 get: Reflect.get
    get() {
      // 每一个 Proxy 中的拦截器名字 在 Reflect 中都存在,因此可以在 Proxy 拦截器中使用 Reflect
      return Reflect.get(...arguments);
    },
  }
);

log(reproxy.age); // log: 23

Si desea crear un proxy que pueda tener todos los métodos de captura y luego reenviar cada método a la API de Reflect correspondiente, puede pasar el segundo parámetro de Proxy directamente como Reflect

const allReflectPro = new Proxy(
  {
    name: "kj",
  },
  Reflect
);

log(allReflectPro.name); // log: kj

receptor invariante

使用捕获器几乎可以改变所有基本方法的行为,但是也有限制;虽然每个捕获的方法都知道目标对象上下文、捕获函数签名,而捕获处理程序的行为必须遵循“捕获器不变式”,防止捕获器定义出现过于反常行为;如目标对象有一个不可配置且不可写的数据属性,那么捕获器返回一个与该属性不同的值时,会抛出 TypeError

const target = {};
Object.defineProperty(target, "const_key", {
  configurable: false, // 不可删除
  writable: false, // 不可写入
  value: "love", // const_key 的 值为 love 字符串
});

const proxy = new Proxy(target, {
  get() {
    // 这里违背了 目标对象 const_key 不可写入(更改)的规则,因此在获取对应的值时会触发 TypeError
    return "update_love";
  },
});

log(proxy.const_key); // TypeError: 'get' on proxy: property 'const_key' is a read-only and non-configurable data property on the proxy target but the proxy did not return its actual value (expected 'love' but got 'update_love')

可撤销代理

使用 new Proxy(target, handler) 创建普通代理来说,这种联系会在代理对象的生命周期内一直持续存在,Proxy.revocable(target,handler) 这个方法返回 revoke 方法可以撤销代理操作,值得注意的是,撤销代理的操作是不可逆的且 revoke 方法是幂等的(即调用多少次结果都一样),撤销代理之后再调用代理会抛出 TypeError;

// 代理对象和撤销代理函数在调用 revocable 在实例化同时生成
const { proxy, revoke } = Proxy.revocable(
  {
    name: "kj",
  },
  Reflect
);

log(proxy.name); // log: kj

revoke();

// 撤销代理之后,再使用代理就会报 TypeError 错误
log(proxy.name); // TypeError: Cannot perform 'get' on a proxy that has been revoked

Supongo que te gusta

Origin juejin.im/post/7253437782333538362
Recomendado
Clasificación