JS - 使用 Reflect 的好处

397 阅读1分钟

使用反射(Reflect)API 时,要记住:

  1. Reflect API 并不限于捕获处理程序;
  2. 大多数 Reflect 方法在 Object 类型上有对应的方法

通常,Object 上的方法适用于通用程序,而反射方法适用于细粒度的对象控制与操作

Reflect API 的好处

状态标记

或许 Object 上也有相同的方法,但是通常 Object 会因为报错而阻塞程序,而 Reflect 返回操作的 boolean 状态值,表示操作成功与否,返回 true 表示操作成功

常见的 Reflect 提供状态标记的 api 有

  • Reflect.defineProperty
  • Reflect.preventExtensions
  • Reflect.setPrototypeOf
  • Reflect.deleteProperty
const obj = {};

try {
  Object.defineProperty(obj, "key", "xxx");
} catch (err) {
  log("err: ", err);
}

// 可以使用 状态标记来 重构上述代码
if (!Reflect.defineProperty(obj, "key", "xx")) {
  log("obj define key failed");
}

用一等函数替代操作符

  • Reflect.get 替代 obj.key / obj["key"]
  • Relfect.set 替代 obj.key = value / obj["key"] = value;
  • Reflect.has 替代 in 或者 with
  • Reflect.deleteProperty 替代 delete 操作符
  • Reflect.construct 替代 new 操作符
const person = {
  name: "jakequc",
  age: 23,
};

// 替代 person.name / person["name"]
log(Reflect.get(person, "name")); // log: jakequc

// 替代 person.name = "new_name" or person["name"] = "new_name"
Reflect.set(person, "name", "new_name");

log(Reflect.get(person, "name")); // log: new_name

// 替代 ( "name" in person )或者 with()
log(Reflect.has(person, "name")); // log: true

// 替代 delete 操作符
log(Reflect.deleteProperty(person, "name")); // log: true 表示删除成功
log(Reflect.has(person, "name")); // log: fasle, 因为上一行已经删除了

// 替代 new 操作符
const arr = Reflect.construct(Array, [1, 2, 3, 4]);
log(arr); // log: [ 1, 2, 3, 4 ]

安全地应用函数

可能某些方法或属性自定义的覆盖了内置的;比如 apply 方法调用函数时,被调用的函数可能也定义了自己的 apply 属性(虽然很小),为了避免这个问题,可以使用 Function.prototype.apply.call 外,还可以使用 Reflect.apply 来代替