Skip to content

反射

ES6(ECMAScript 2015)引入了Reflect,这是一个内置对象,它提供了一种用于拦截并定义基本操作的方法集合。与Proxy不同,Reflect并不直接创建代理行为,而是提供了与Proxy处理程序相同的方法,使得对对象的操作更加一致和可预测。通过Reflect,开发者可以更方便地执行对象的基本操作,如属性访问、函数调用等。

Reflect 的主要用途

  • 统一操作对象的方式Reflect将原本分散在多个地方的对象操作方法(例如定义属性的方法Object.defineProperty)集中到了一起,并以函数的形式提供。
  • 与 Proxy 协同工作Reflect的方法可以直接对应到Proxy的处理器(handler)方法上,这使得在拦截操作的同时可以使用Reflect来完成默认行为。

常见的 Reflect 方法

1. Reflect.get(target, propertyKey[, receiver])

获取对象属性的值。

javascript
let obj = { name: "Alice" };
console.log(Reflect.get(obj, "name")); // 输出: Alice

2. Reflect.set(target, propertyKey, value[, receiver])

设置对象属性的值。

javascript
let obj = {};
Reflect.set(obj, "age", 30);
console.log(obj.age); // 输出: 30

3. Reflect.has(target, propertyKey)

相当于propertyKey in target操作符。

javascript
let obj = { name: "Alice" };
console.log(Reflect.has(obj, "name")); // 输出: true

4. Reflect.deleteProperty(target, propertyKey)

删除对象的属性。

javascript
let obj = { name: "Alice" };
Reflect.deleteProperty(obj, "name");
console.log("name" in obj); // 输出: false

5. Reflect.apply(target, thisArgument, argumentsList)

调用一个函数,并指定this值以及传递给目标函数的参数列表。

javascript
function greet(name) {
  return `Hello, ${name}!`;
}
console.log(Reflect.apply(greet, null, ["Alice"])); // 输出: Hello, Alice!

6. Reflect.construct(target, argumentsList[, newTarget])

类似于new target(...argumentsList)的行为,但允许你指定构造函数。

javascript
class Person {
  constructor(name) {
    this.name = name;
  }
}

let instance = Reflect.construct(Person, ["Alice"]);
console.log(instance.name); // 输出: Alice

使用场景示例

结合ProxyReflect可以实现一些高级功能,比如日志记录、输入验证等。

  • 示例:使用ProxyReflect进行简单的属性访问日志记录:
javascript
let target = { name: "Alice" };
let handler = {
  get(target, propertyKey, receiver) {
    console.log(`Getting ${propertyKey}`);
    return Reflect.get(target, propertyKey, receiver);
  },
  set(target, propertyKey, value, receiver) {
    console.log(`Setting ${propertyKey} to ${value}`);
    return Reflect.set(target, propertyKey, value, receiver);
  },
};

let proxy = new Proxy(target, handler);

proxy.name; // 控制台输出: Getting name
proxy.age = 25; // 控制台输出: Setting age to 25

在这个例子中,我们利用Proxy来拦截对对象属性的访问,并使用Reflect来执行默认的行为。这样可以在不改变原有逻辑的情况下添加额外的功能,比如在这里我们添加了日志记录功能。

Reflect提供的这些方法不仅提高了代码的一致性和可读性,还为 JavaScript 编程带来了更多的灵活性和可能性。通过合理利用Reflect,可以编写出更加高效、简洁的代码。

Released under the MIT License.