使用反射(Reflect)API 时,要记住:
- Reflect API 并不限于捕获处理程序;
- 大多数 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 来代替