JavaScript Proxy() 构造函数、Proxy对象

Proxy() 构造函数

Proxy() 构造函数用于创建 Proxy 对象。

语法

new Proxy(target, handler)

可以使用 Proxy() 构造函数来创建一个新的 Proxy 对象。构造函数接收两个必须的参数:

  • target
    是要创建的对象,即要使用 Proxy 包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。
  • handler
    是定义了代理的自定义行为的对象,其属性是定义了在对代理执行操作时的行为的函数。

注意Proxy() 只能通过 new 关键字来调用。如果不使用 new 关键字调用,则会抛出 TypeError

Proxy对象

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

语法

const p = new Proxy(target, handler)

handler对象的方法

handler 对象是一个容纳一批特定属性的占位符对象。它包含有 Proxy 的各个捕获器(trap)。

所有的捕捉器都是可选的。如果没有定义某个捕捉器,那么就会保留源对象的默认行为。

一个空的处理器(handler)将会创建一个与被代理对象行为几乎完全相同的代理对象。通过在 handler 对象上定义一组函数,你可以自定义被代理对象的一些特定行为。
如果在 handler 中存在相应的捕捉器,则它将运行,并且 Proxy 有机会对其进行处理,否则将直接对 target 进行处理。

示例:

let target = {
   
   };
let proxy = new Proxy(target, {
   
   }); // 空的 handler 对象

proxy.test = 5; // 写入 proxy 对象
console.log('target:', target, 'proxy:', proxt); // target和proxy中都有test属性!
console.log(target.test); // 5,test 属性出现在了 target 中!

console.log(proxy.test); // 5,我们也可以从 proxy 对象读取它

for(let key in proxy) console.log(key); // test,迭代也正常工作 

在这个示例中, handler 对象为空,没有捕捉器,所有对 proxy 的操作都直接转发给了 target

  1. 写入操作 proxy.test = 5 会将值写入 target。
  2. 读取操作 proxy.test 会从 target 返回对应的值。
  3. 迭代 proxy 会从 target 返回对应的值。
    此时,proxy 是一个 target 的透明包装器(wrapper)。它没有自己的属性。如果 handler 为空,则透明地将操作转发给 target

对于对象的大多数操作,JavaScript 规范中有一个所谓的“内部方法”,它描述了最底层的工作方式。
Proxy 捕捉器会拦截 对底层被代理对象的调用。
例如,通过定义 set() 可以自定义写入被代理对象的属性;通过定义 get() 可以自定义被代理对象的属性访问器。
常见的拦截操作和对应的捕捉器函数有:

  • set(target, propKey, value, receiver):拦截对象的设置属性操作,返回一个布尔值表示是否设置成功。
  • get(target, propKey, receiver):拦截对象的读取属性操作,返回属性值。
  • has(target, propKey):拦截对象的 in 操作符,返回一个布尔值表示对象是否包含该属性。
  • deleteProperty(target, propKey):拦截对象的 delete 操作符,返回一个布尔值表示是否删除成功。
  • ownKeys()Object.getOwnPropertyNames 方法和 Object.getOwnPropertySymbols 方法的捕捉器函数。
  • getPrototypeOf()Object.getPrototypeOf 方法的捕捉器。
  • setPrototypeOf()Object.setPrototypeOf 方法的捕捉器。
  • isExtensible()Object.isExtensible 方法的捕捉器。
  • preventExtensions()Object.preventExtensions 方法的捕捉器。
  • getOwnPropertyDescriptor()Object.getOwnPropertyDescriptor 方法的捕捉器。
  • defineProperty()Object.defineProperty 方法的捕捉器。
  • apply(target, thisArg, args):拦截函数的调用操作,返回调用结果。
  • construct(target, args, newTarget):拦截 new 操作符,返回一个对象。

handler.set()

handler.set() 方法是设置属性值操作的捕获器。文档请看mdn

语法

new Proxy(target, {
   
   
  set(target, property, value, receiver) {
   
   
  }
});

handler.set() 方法用于拦截设置属性值的操作。this 绑定在 handler 对象上。
以下是传递给 set() 方法的参数:

  • target
    目标对象。该对象被作为第一个参数传递给 new Proxy
  • property
    目标属性名称(将被设置的属性名或 Symbol)。
  • value
    目标属性值。
  • receiver
    最初接收赋值的对象。通常是 proxy 本身,但 handlerset 方法也有可能在原型链上,或以其他方式被间接地调用(因此不一定是 proxy 本身)。

返回值

  • 返回 true 代表属性设置成功。
  • 在严格模式下,如果 set() 方法返回 false,那么会抛出一个 TypeError 异常。

使用示例

let numbers = [];
numbers = new Proxy(numbers, {
   
    // (*)
  set(target, prop, val) {
   
    // 拦截写入属性操作
    if (typeof val == 'number') {
   
   
      target[prop] = val;
      return true;  // 此处必须要return true,表示属性设置成功
    } else {
   
   
      return false;
    }
  }
});

numbers.push(1); // 添加成功
numbers.push("test"); // TypeError(proxy 的 'set' 返回 false)

如果写入操作(setting)成功,set 捕捉器应该返回 true,否则返回 false(触发 TypeError)。

handler.get()

handler.get() 方法用于拦截对象的读取属性操作。文档请看mdn

语法

var p = new Proxy(target, {
   
   
  get: function (target, property, receiver) {
   
   },
});

以下是传递给 get() 方法的参数:

  • target
    目标对象。该对象被作为第一个参数传递给 new Proxy
  • property
    目标属性名称。
  • receiver
    Proxy 或者继承 Proxy 的对象。

返回值

  • get 方法可以返回任何值。

使用示例

let numbers = [0, 1, 2];
numbers = new Proxy(numbers, {
   
   
  get(target, prop) {
   
   
    if (prop in target) {
   
   
      return target[prop];
    }
  }
});

alert( numbers[1] ); // 1
alert( numbers[123] ); // undefined(没有这个数组项)

如果获取数组中不存在的值,会得到 undefined
get捕获器,可以给不存在的值一个默认值。

handler.deleteProperty()

handler.deleteProperty() 方法用于拦截对对象属性的 delete 操作。

deleteProperty语法

var p = new Proxy(target, {
   
   
  deleteProperty: function (target, property) {
   
   },
});

参数

  • target
    目标对象。
  • property
    待删除的属性名。

返回值
deleteProperty 必须返回一个 Boolean 类型的值,表示了该属性是否被成功删除。

使用示例

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值