前端面试题,利用给定接口获得闭包内部对象

var o = (function() {
    var person = {
        name: 'Vincent',
        age: 24,
    };
    return {
        run: function(k) {
            return person[k];
        },
    }
}());

在不改变上面的代码情况下, 怎么得到原有的 person 对象?


假如在 person 中加上 __proto__: null,原先大家回答的方法就失效了,但此时仍旧有​​解,有兴趣者欢迎挑战。

阅读 12.1k
8 个回答
Object.prototype.__defineGetter__('get', function(){
    return this;
});


console.log(o.run('get'));

基于 @小俞 的方法,我写个可能是更好的选择的吧!

javascriptObject.defineProperty(Object.prototype, 'self', {
    get: function () {return this;},
    set: function (value) {return this},
    configurable: true
    // 该属性的存在是确保该属性可被delete方法删除
});

var person = o.run('self');
delete Object.prototype.self;
//由于不推荐使用prototype来扩展自己定义的属性(扩展标准规定的除外),这里把扩展再去掉。

相较 小俞 的做法,这里面的用到的都是共有方法,不是__xxx__这种更为私有的方法(__xxx__)这种可能在不同浏览器里的实现不一样。

对于这种问题我们首先要分析它的代码结构:
1.看它的返回值,我们看到它最终的一个返回值是一个json对象,这个json对象有一个run的函数。
2.分析函数,run这个函数实际上只做了一件事件,接受参数通过参数调用上面声明的person对象的值。
3.再看你的问题,你是想问在如何不修改已有的代码情况下打印person对象。
4.返回来看第2点,我们已经知道,通过o.run("name");实际上就是操作person对象本身,它返回的结果是Vincent

你的提问并不是很明确...
1、你指的“把正规person对象打印出来”是用console.log这类方法显示在控制面板里?
2、这道题目其实是闭包的问题,javascript里的闭包是设计成对外隐藏内部变量的。如果你想用“正规”方式打印出来,貌似是对js闭包变量安全性做一次否定。
3、你确定这道题目是个前端面试题?那你心中是否已经从面试者那获得了这道题的答案?如果是你自己对闭包概念的疑问的话,还望你别加上前端面试题这一title

Ps: 如果想在chrome这类浏览器的console面板里查看这个闭包里的数据到时可以通过console.log(o),找到run函数下的查看里面的person,也就是你指的原始person对象

Object.defineProperty(Object.prototype, 'get', {get: function(){
    return this;
}});


console.log(o.run('get'));
推荐问题
宣传栏