__defineGetter__ 引发的思考
问题
那天朋友分享了一个面试题,自己当时不会,代码如下:
(function(){
var u = { a: 1, b: 2 };
var r = {
m: function(k){
return u[k];
}
}
window.r = r;
})()
var R = window.r;
alert(r.m('a'))
很简单,alert 的结果是 1。
但是题目却是另外一个说法,能不能通过 r.m 获取到 u?
当时听到这个问题也凌乱了,压根就不知道啥意思,通过r.m获取到u?
实际上这个问题问的重点是当 u 不知道的时候,如何通过 u[attribute] 这种方式来获得 u 的自身。那么问题就来了,你需要传递一个 attribute,r.m(attribute) 返回 u。
解决方案
有一个非标准的,而且将被废弃的方法
Object.prototype.__defineGetter__
可以给对象指定一个参数并且绑定一个函数,当未来你在此对象的实例上调用此参数时,绑定的函数会被调用,该参数是被定义在prototype
上,所以此参数就是一个实例属性,那个函数被调用时,是以当前实例为上下文。
哦?那这样的话 u 就是一个实例,给 u 绑定一个参数,当此参数调用的时候返回 u 自身不就好啦?
怎么绑定呢?u 是一个 Object 的实例,它继承自 Object,那么就给 Object.prototype
定义一个属性,使得该属性访问时调用的函数返回 this 就可以了,所以,解决方案如下:
Object.prototype.__defineGetter__('uuu', function(){ return this; });
alert(R.m('uuu'));
此题这样就算解决了,此题的精髓主要是三点:
- 你能否想到通过属性访问自身
- 你能否想到使用原型继承来定义访问自身的属性
- 你是否知道
Object.prototype.__defineGetter__
优化解决方案
为了不污染 Object 原型链,我们应该定义一个随机的参数来返回自身,当使用之后再删除之,那么比较完美的方案应该是:
Object.prototype.__defineGetter__('x123c3', function(){ return this; });
alert(R.m('x123c3'));
delete Object.prototype['x123c3']
既然废弃了,有没有替代方法?
嗯,本来自己不太清楚,感谢网友的帮忙。
目前存在这么一个 API:Object.defineProperty(obj, 'key', { // descriptor });
参阅API
使得可以直接在某一对象上定义一个属性,这个属性可以是添加或修改现有的属性,前两个参数都很好理解,obj就是要修改的对象,key就是属性名, descriptor 是一个对象,用来声明新添属性的一些特性,包括6个参数:
- configurable:默认false,表示此属性是否可用
delete
删除 - enumerable: 默认为false,表示此属性是否可被
for...in、Object.keys
遍历到 - value:默认undefined,此属性的值,可以是任何JavaScript类型
- writable:默认为false,此属性是否可被改写
- get:默认undefined,指定一个函数,当属性被调用时,此函数也被调用,默认为返回属性值
- set:默认undefined,指定一个函数,当属性被赋值时,此函数也被调用,仅接受一个参数,参数为属性被赋的值
那么上面的解决方案可以改为:
Object.defineProperty(Object.prototype, 'blablabla', {
get : function(){
return this;
}
});
console.log(R.m('blablabla'));
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
上一篇: React.js 要点、坑点
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论