Appearance
Reflect
在 ES6 中增加这个对象的目的:
- 将 Object 对象的一些明显属于语言内部的方法(比如 Object.defineProperty),放到 Reflect 对象上。现阶段,某些方法同时在 Object 和 Reflect 对象上部署,未来的新方法将只部署在 Reflect 对象上。也就是说,从 Reflect 对象上可以拿到语言内部的方法。
- 修改某些 Object 方法的返回结果,让其变得更合理。比如,Object.defineProperty(obj, name, desc)在无法定义属性时,会抛出一个错误,而 Reflect.defineProperty(obj, name, desc)则会返回 false。
- 让 Object 操作都变成函数行为。某些 Object 操作是命令式,比如
name in obj
和delete obj[name]
,而Reflect.has(obj, name)
和Reflect.deleteProperty(obj, name)
让它们变成了函数行为。 - Reflect 对象的方法与 Proxy 对象的方法一一对应,只要是 Proxy 对象的方法,就能在 Reflect 对象上找到对应的方法。这就让 Proxy 对象可以方便地调用对应的 Reflect 方法,完成默认行为,作为修改行为的基础。也就是说,不管 Proxy 怎么修改默认行为,你总可以在 Reflect 上获取默认行为。
js
var loggedObj = new Proxy(obj, {
get(target, name) {
console.log("get", target, name)
return Reflect.get(target, name)
},
deleteProperty(target, name) {
console.log("delete" + name)
return Reflect.deleteProperty(target, name)
},
has(target, name) {
console.log("has" + name)
return Reflect.has(target, name)
},
})
上面代码中,每一个 Proxy 对象的拦截操作(get、delete、has),内部都调用对应的 Reflect 方法,保证原生行为能够正常执行。添加的工作,就是将每一个操作输出一行日志。
注意: Reflect 不是一个函数对象,因此它是不可构造的。(相当于 Java 的对象提供的全是静态方法,不能被 new 操作)
Reflect.construct
Reflect.construct 其实就是实例化构造函数,通过传参形式的实现, 执行的方式不同, 效果其实一样, construct 的第一个参数为构造函数, 第二个参数由参数组成的数组或者伪数组。
我们先看最基本的两个参数:
js
var date = Reflect.construct(Date, [2020, 5, 15])
console.log(date instanceof Date) // true
console.log(date.getFullYear()) // 2020
其功能就像 new
js
var date = new Date([2020, 5, 15])
console.log(date instanceof Date) // true
console.log(date.getFullYear()) // 2020
- 第三个参数 newTarget
新创建对象的原型对象, 参考 new.target 操作符,默认值为 target。
即将 newTarget 原型上的属性复制给 target
js
function OtherClass() {
console.log("OtherClass")
console.log(new.target)
this.age = 100
this.fAge = "f-100"
}
OtherClass.prototype.fName = "fName"
OtherClass.prototype.name = "f-name"
function OneClass(name, age) {
console.log("OneClass")
console.log(new.target)
this.name = name
this.age = age
}
OneClass.prototype.name = "c-name"
var result = Reflect.construct(OneClass, ["oneClass", 10], OtherClass)
console.log(result)
console.log(result instanceof OneClass) // false
console.log(result instanceof OtherClass) // true
可见对于第三个参数其作用:
修改了构造函数的指向 (为 OtherClass)
将实例对象的原型链指向 OtherClass 原型链