本文在我博客上的地址: http://lpgray.me/article/46/javascript
那天朋友分享了一个面试题,本身当时不会,代码以下:java
(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。this
有一个非标准的,并且将被废弃的方法
Object.prototype.__defineGetter__
能够给对象指定一个参数而且绑定一个函数,当将来你在此对象的实例上调用此参数时,绑定的函数会被调用,该参数是被定义在prototype
上,因此此参数就是一个实例属性,那个函数被调用时,是以当前实例为上下文。prototype
哦?那这样的话u就是一个实例,给u绑定一个参数,当此参数调用的时候返回u自身不就好啦?code
怎么绑定呢?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'));