1. 什么是 Reflect
Reflect 可以调用对象的基本方法(内部方法),在 ES6 之前我们是没有任何方法去直接调用对象的基本方法的。只能间接调用,间接调用它又会给你做一些额外得事。
2. 对象的基本方法
什么是对象的基本方法呢,对象内部运行的方法就是对象的基本方法。对象的基本方法有哪些,它对应的反射方法是什么。如下:
// 基本方法 => 反射方法
[[GetOwnProperty]] => getPrototypeOf();
[[SetPrototypeOf]] => setPrototypeOf();
[[IsExtensible]] => isExtensible();
[[PreventExtensions]] => preventExtensions();
[[GetOwnProperty]] => getOwnPropertyDescriptor();
[[DefineOwnProperty]] => defineProperty();
[[HasProperty]] => has();
[[GET]] => get();
[[SET]] => set();
[[DELETE]] => deleteProperty();
[[OwnPropertyKeys]] => ownKeys()
3. Reflect 有什么用
我们举个例子,下面这两个语句是同样的作用,都是设置 name 的值:
let obj = { name: "yq" };
obj.name = "yqcoder";
console.log(obj); // { name: 'yqcoder' }
let obj = { name: "yq" };
Reflect.set(obj, "name", "yqcoder");
console.log(obj); // { name: 'yqcoder' }
那么既然都是做的同样的是,它们有什么区别呢。区别在于,通过语法或者一些 API 去调用对象的内部方法的话,它会经过一些规则和步骤,在这些规则和步骤当中,有一步是在调用这个内部方法。如果你不希望有这些额外步骤存在,那就需要你直接去调用对象的基本方法了。使用 Reflect。
4. 为什么要用 Reflect
有小伙伴就问了,我为啥要直接调用对象的基本方法,用语法进行对象操作不好吗。肯定是因为 Reflect 可以做一些语法做不到的事,我们才会去使用 Reflect。比如:
let obj = {
a: 1,
b: 2,
get c() {
return this.a + this.b;
},
};
obj.c; // 3
上面的 obj.c 实际是通过[[GET]](obj, 'c', obj),去得到的值,当我们想通过 obj.c 改变 this 的指向,这时做不到的,用 Reflect 就可以。如下,就改变了 this 的指向。
let obj = {
a: 1,
b: 2,
get c() {
return this.a + this.b;
},
};
Reflect.get(obj, "c", { a: 3, b: 4 }); // 7
另外,有的时候我们去封装代理对象的时候,也需要用到 Reflect,比如,我们需要得到这么一个代理,访问 proxy.c 时,需要将 a,b 一起打印出来。
let obj = {
a: 1,
b: 2,
get c() {
return this.a + this.b;
},
};
const proxy = new Proxy(obj, {
get(target, key) {
console.log(key);
return Reflect.get(target, key, proxy);
},
});
proxy.c; // c a b
再比如,我们需要获取到对象得所有属性
let obj = {
a: 1,
b: 2,
};
Object.defineProperty(obj, "c", {
value: 3,
enumerable: false,
});
Object.keys(obj); // ['a', 'b']
Reflect.ownKeys(obj); // ['a', 'b', 'c']