代理与反射

Reflect

某些情况下应该优先使用反射 API,这是有一些理由的。

1、反射 API 与对象 API 在使用反射 API 时,要记住:

  • 反射 API 并不限于捕获处理程序;

  • 大多数反射 API 方法在 Object 类型上有对应的方法。 通常,Object 上的方法适用于通用程序,而反射方法适用于细粒度的对象控制与操作。

2、状态标记 很多反射方法返回称作“状态标记”的布尔值,表示意图执行的操作是否成功。有时候,状态标记 比那些返回修改后的对象或者抛出错误(取决于方法)的反射 API 方法更有用。例如,可以使用反射 API 对下面的代码进行重构:

// 初始代码
const o = {};
 try {
   Object.defineProperty(o, 'foo', 'bar');
   console.log('success');
 } catch(e) {
   console.log('failure');
}

在定义新属性时如果发生问题,Reflect.defineProperty()会返回 false,而不是抛出错误。 因此使用这个反射方法可以这样重构上面的代码: // 重构后的代码

const o = {};
   if(Reflect.defineProperty(o, 'foo', {value: 'bar'})) {
   console.log('success');
   } else {
   console.log('failure');
}

以下反射方法都会提供状态标记:

-Reflect.defineProperty() -Reflect.preventExtensions() -Reflect.setPrototypeOf() -Reflect.set() -Reflect.deleteProperty()

3、 用一等函数替代操作符 以下反射方法提供只有通过操作符才能完成的操作。

  • Reflect.get():可以替代对象属性访问操作符。

  • Reflect.set():可以替代=赋值操作符。

  • Reflect.has():可以替代 in 操作符或 with()。

  • Reflect.deleteProperty():可以替代 delete 操作符。

  • Reflect.construct():可以替代 new 操作符。

4、 安全地应用函数 在通过 apply 方法调用函数时,被调用的函数可能也定义了自己的 apply 属性(虽然可能性极小)。 为绕过这个问题,可以使用定义在 Function 原型上的 apply 方法,比如: Function.prototype.apply.call(myFunc, thisVal, argumentList); 这种可怕的代码完全可以使用 Reflect.apply 来避免: Reflect.apply(myFunc, thisVal, argumentsList);

Last updated