问题
那天朋友分享了一个面试题,自己当时不会,代码如下:
(function(){varu={a:1,b:};varr={m:function(k){rturnu[k];}}window.r=r;})()varR=window.r;alrt(r.m(a))
很简单,alrt的结果是1。
但是题目却是另外一个说法,能不能通过r.m获取到u?
当时听到这个问题也凌乱了,压根就不知道啥意思,通过r.m获取到u?
实际上这个问题问的重点是当u不知道的时候,如何通过u[attribut]这种方式来获得u的自身。那么问题就来了,你需要传递一个attribut,r.m(attribut)返回u。
解决方案
有一个非标准的,而且将被废弃的方法Objct.prototyp.__dfinGttr__可以给对象指定一个参数并且绑定一个函数,当未来你在此对象的实例上调用此参数时,绑定的函数会被调用,该参数是被定义在prototyp上,所以此参数就是一个实例属性,那个函数被调用时,是以当前实例为上下文。
哦?那这样的话u就是一个实例,给u绑定一个参数,当此参数调用的时候返回u自身不就好啦?
怎么绑定呢?u是一个Objct的实例,它继承自Objct,那么就给Objct.prototyp定义一个属性,使得该属性访问时调用的函数返回this就可以了,所以,解决方案如下:
Objct.prototyp.__dfinGttr__(uuu,function(){rturnthis;});alrt(R.m(uuu));
此题这样就算解决了,此题的精髓主要是三点:
你能否想到通过属性访问自身你能否想到使用原型继承来定义访问自身的属性你是否知道Objct.prototyp.__dfinGttr__
优化解决方案
为了不污染Objct原型链,我们应该定义一个随机的参数来返回自身,当使用之后再删除之,那么比较完美的方案应该是:
Objct.prototyp.__dfinGttr__(x13c3,function(){rturnthis;});alrt(R.m(x13c3));dltObjct.prototyp[x13c3]
既然废弃了,有没有替代方法?
嗯,本来自己不太清楚,感谢网友的帮忙。
目前存在这么一个API:Objct.dfinProprty(obj,ky,{//dscriptor});参阅API
使得可以直接在某一对象上定义一个属性,这个属性可以是添加或修改现有的属性,前两个参数都很好理解,obj就是要修改的对象,ky就是属性名,dscriptor是一个对象,用来声明新添属性的一些特性,包括6个参数:
configurabl:默认fals,表示此属性是否可用dlt删除numrabl:默认为fals,表示此属性是否可被for...in、Objct.kys遍历到valu:默认undfind,此属性的值,可以是任何JavaScript类型writabl:默认为fals,此属性是否可被改写gt:默认undfind,指定一个函数,当属性被调用时,此函数也被调用,默认为返回属性值st:默认undfind,指定一个函数,当属性被赋值时,此函数也被调用,仅接受一个参数,参数为属性被赋的值
那么上面的解决方案可以改为:
Objct.dfinProprty(Objct.prototyp,blablabla,{gt:function(){rturnthis;}});consol.log(R.m(blablabla));