这章建议直接看原文,引入Reflect主要解决的是当代理getter时的this指向问题(可能也不止有这个问题)
如下代码:
const obj = {
foo: 1,
get bar() {
return this.foo
}
}
当使用Proxy代理obj时,其中的get函数bar实际返回额是foo的值,而当我们在渲染函数中使用时proxy.bar时,该bar访问的是obj.foo
好吧,其实我没搞懂问题究竟出在哪。
const p = new Proxy(obj, {
get(target, key) {
track(target, key)
// 注意,这里原本没有使用 Reflect.get 完成读取
// return target[key]
// 使用 Reflect.get 返回读取到的属性值
return Reflect.get(target, key, receiver)
},
// 省略部分代码
})
this
指向,在Proxy
代理的get/set
方法中,最后存在一个参数receiver
, 其指向的是代理实例本身,而target
指向的是原对象。但是我们的操作是基于代理实例而不是原对象,所以为了前后指向一致(虽然似乎修改原对象好像也没问题,甚至直接使用receiver[key]
的方式好像也行)。Reflect
针对对象操作拥有更好的错误兼容,例如重复的属性定义,如果使用Object.defineProperty
进行同一个属性两次定义会报错, 而如果使用Reflect.defineProperty
进行定义则只会在第二次定义返回false,而非报错。并且新的语言内部对象方法将只在Reflect
上实现。参考
JavaScript中一切皆对象
对象如果没有按照特定版本的ESMA规范定义的内部方法([[GET]]
,[[SET]]
,[[Delete]]
等)的对象即为异质对象。
而我们在实例化Proxy时传入的get/set拦截方法等则是用来自定义代理本身的内部方法和行为的。
对一个普通对象所有可能的读取操作