美文网首页
在es6 Proxy中,推荐使用Reflect.get而不是ta

在es6 Proxy中,推荐使用Reflect.get而不是ta

作者: 龙_猫 | 来源:发表于2019-10-20 12:20 被阅读0次

目前中文检索得不到这个问题的答案,大多数的博客都是直接使用了Reflect.get而没有给出原因。为了解释这个问题,首先还要说明另一个问题。

Reflect.get(target, prop, receiver) 以及 Proxy中的 handler.get(target, prop, receiver) 这当中的receiver是什么?

直接摘抄MDN的说明

Reflect.get(target, prop, receiver)中的参数receiver:如果target对象中指定了getter,receiver则为getter调用时的this值。

handler.get(target, prop, receiver)中的参数receiver:Proxy或者继承Proxy的对象。

参数receiver存在的意义

单独来看,我很难想出receiver参数的使用场景,甚至会认为这个参数没有存在的意义,但既然这么设计就一定有它存在的意义。先看下面的例子:

let People = new Proxy({
  _name:'zky',
  get name(){
    return this._name
  }
},{
  get:function(target,prop,receiver){
    return target[prop]
    }
  })
let Man = {_name:'zky_man'}
Man.__proto__ = People // Man继承People
console.log(Man._name) // zky_man
console.log(Man.name) // zky

问题来了,Man中已经存在_name属性,但这里Man.name返回的却是原型链上的_name属性,
原因很好解释:get name中的this默认绑定为People

那怎么解决这个问题呢?这里就该receiver上场了,修改上面的例子:

let People = new Proxy({_name:'zky'},{
  get:function(target,prop,receiver){ // receiver指向的是get的调用者
    return Reflect.get(target,prop,receiver) // 调用get name函数时,this被绑定到receiver
    }
  })
let Man = {
  _name:'zky_man',
  get name(){
    return this._name
  }
  }
Man.__proto__ = People // Man继承People
console.log(Man._name)// zky_man
console.log(Man.name) // zky_man

到这里问题就已经完美解决了,这也就是Reflect.gettarget[key]更好的原因。

调用Man.name时经过了以下几步

  1. proxy拦截,调用handler.get
  2. handler.get中传入的receiver参数指向调用者--Man
  3. 调用Reflect.get,由于target中的name指定了getterReflect.get自动将调用的getter函数的this绑定到receiver,也就是Man

如果没看懂请结合例子及上面对receiver参数的说明进行理解

参考文献:https://javascript.info/proxy?tdsourcetag=s_pctim_aiomsg#proxying-a-getter

相关文章

网友评论

      本文标题:在es6 Proxy中,推荐使用Reflect.get而不是ta

      本文链接:https://www.haomeiwen.com/subject/tsnomctx.html