JavaScript Proxy 和 Reflect

预计阅读时间1 分 133 views

在 JavaScript 中,我们经常需要监听对象的各种操作,比如属性的读取、设置、删除,以及函数的调用等。传统的方式是通过重写对象的 getter、setter 等方法来实现,但这种方式不够灵活,代码也比较冗杂。为了解决这个问题,ES6 引入了 Proxy 和 Reflect,它们为我们提供了一种更优雅、更强大的方式来拦截和自定义 JavaScript 对象的操作。

Proxy 对象

Proxy 对象用于创建一个对象的代理,从而拦截并自定义对该对象的操作。

const proxy = new Proxy(target, handler);
  • target: 被代理的目标对象。
  • handler: 一个对象,包含了用于拦截目标对象操作的“陷阱”方法。

常用陷阱方法:

陷阱方法描述
get(target, prop, receiver)拦截对象的属性读取
set(target, prop, value, receiver)拦截对象的属性设置
deleteProperty(target, prop)拦截对象的属性删除
has(target, prop)拦截 in 操作符
apply(target, thisArg, args)拦截函数调用
construct(target, args)拦截 new 操作符

Reflect API

Reflect API 提供了一组用于执行底层操作的静态方法,与 Proxy 的陷阱方法一一对应。使用 Reflect 可以确保在拦截操作时,保持默认的行为。

常用静态方法:

静态方法描述
Reflect.get(target, prop, receiver)获取对象的属性值
Reflect.set(target, prop, value, receiver)设置对象的属性值
Reflect.deleteProperty(target, prop)删除对象的属性
Reflect.has(target, prop)检查对象是否拥有某个属性
Reflect.apply(target, thisArg, args)调用函数
Reflect.construct(target, args)使用 new 操作符调用构造函数

示例代码

以下代码展示了如何使用 Proxy 和 Reflect 来实现一个简单的属性验证功能:

// 定义一个用户对象
const user = {
  name: 'John',
  age: 30
};

// 创建一个拦截器对象,用于拦截对属性的赋值操作
const handler = {
  // 当设置属性值时,此函数被调用
  set(target, prop, value) {
    // 检查属性是否为 'age' 且值类型是否为非数字
    if (prop === 'age' && typeof value !== 'number') {
      // 如果类型不匹配,抛出错误
      throw new TypeError('Age must be a number.');
    }
    // 如果验证通过,使用Reflect.set进行属性赋值
    return Reflect.set(target, prop, value);
  }
};

// 使用Proxy创建一个代理对象,该对象在属性访问和赋值时会经过handler的处理
const userProxy = new Proxy(user, handler);

// 打印代理对象的name属性,应该输出原始user对象的name值
console.log(userProxy.name); // 输出: "John"

// 尝试更新代理对象的age属性为一个有效的数字
userProxy.age = 35;
console.log(userProxy.age); // 输出: 35

// 尝试更新代理对象的age属性为一个字符串,这将触发异常
try {
  userProxy.age = 'thirty-five';
} catch (error) {
  // 捕获并打印错误信息
  console.error(error.message); // 输出: "Age must be a number."
}

在这个例子中,我们创建了一个 user 对象,并使用 Proxy 创建了一个代理对象 userProxy。在 handler 对象中,我们定义了一个 set 陷阱方法,用于拦截对 age 属性的设置操作。如果设置的值不是数字,则抛出一个异常,否则使用 Reflect.set 方法设置属性值。

分享此文档

JavaScript Proxy 和 Reflect

或复制链接

本页目录