资讯专栏INFORMATION COLUMN

__defineGetter__ 引发的思考

Charles / 3048人阅读

摘要:本文在我博客上的地址问题那天朋友分享了一个面试题,自己当时不会,代码如下很简单,的结果是。那么问题就来了,你需要传递一个,返回。

本文在我博客上的地址: http://lpgray.me/article/46/

问题

那天朋友分享了一个面试题,自己当时不会,代码如下:

(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"));

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/85426.html

相关文章

  • JS-创建对象

    摘要:创建对象使用或者对象字面量都可以创建对象,但是这样创建的对象过于简单,不易于对象的属性与方法的扩展与继承。下面讲的对象可以与中的做类比。通过调用构造函数创建的那个对象实例的原型对象。 创建对象 使用new Object()或者对象字面量都可以创建对象,但是这样创建的对象过于简单,不易于对象的属性与方法的扩展与继承。 下面讲的对象可以与JavaEE中的bean做类比。 工厂模式 对,首...

    william 评论0 收藏0
  • JavaScript学习之对象拷贝

    摘要:对象拷贝可遍历属性浅拷贝简单的浅拷贝可以用,对存取器定义的对象也试用深拷贝属性描述对象的拷贝这是个浅拷贝深拷贝不可遍历属性对象的拷贝例如拷贝获得共同的原型,与是兄弟关系说明也继承了原型,同级别简洁化版 对象拷贝 可遍历属性 浅拷贝 if(typeof Object.prototype.copy != function) { Object.prototype.copy = fun...

    Aklman 评论0 收藏0
  • 浅谈:快速理解JS原型与原型链

    摘要:中有基本类型和复杂类型的区分。原型与原型链这里,就引入了两个新的概念。原型对象就是用来存放声明对象中共有的那部分属性。而原型对象自身也是一个对象,它也有自己的原型对象。这样层层上溯,就形成了一个类似链表的结构,这就是原型链。 JavaScript中有基本类型和复杂类型的区分。 当我们在声明一个基本类型时: var n1= 1; console.log(n1); //1 这时我们可以用N...

    ZoomQuiet 评论0 收藏0
  • 一道面试题引发思考 --- Event Loop

    摘要:想必面试题刷的多的同学对下面这道题目不陌生,能够立即回答出输出个,可是你真的懂为什么吗为什么是输出为什么是输出个这两个问题在我脑边萦绕。同步任务都好理解,一个执行完执行下一个。本文只是我对这道面试题的一点思考,有误的地方望批评指正。 想必面试题刷的多的同学对下面这道题目不陌生,能够立即回答出输出10个10,可是你真的懂为什么吗?为什么是输出10?为什么是输出10个10?这两个问题在我脑...

    betacat 评论0 收藏0
  • 通过源码解析 Node.js 启动时第一个执行 js 文件:bootstrap_node.js

    摘要:注很多以前的源码分析文章中,所写的第一个执行的文件代码为,但这个文件在中已被移除,并被拆解为了等其他下的文件,为正文作为第一段被执行的代码,它的历史使命免不了就是进行一些环境和全局变量的初始化工作。 大家可能会好奇,在 Node.js 启动后,第一个执行的 JavaScript 文件会是哪个?它具体又会干些什么事? 一步步来看,翻开 Node.js 的源码,不难看出,入口文件在 src...

    TNFE 评论0 收藏0

发表评论

0条评论

Charles

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<