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']