关闭的全球对象

时间:2013-03-27 20:24:56

标签: javascript node.js

JS中有一些非常基本的东西我不确定。所以我想问一下。

全局对象是window(当然对于node.js来说是global)。因此,我们可以通过名称window[myVariableName]来获取变量的值。

问题是如何使用闭包的局部变量来实现?

function myFunction()
{
  // some code here    
  console.log(global_object[myVariableName]);
}

当变量对于当前闭包是全局的但不属于window对象时,甚至可以按名称获取变量的值。

根据我对JS及其工作原理的了解 - 这是不可能的。

顺便说一句,这是一个非常受欢迎的访谈问题,如何通过名称来获取变量的值,并且从未提及变量是全局的:)。

3 个答案:

答案 0 :(得分:4)

eval('var value = ' + myVariableName + ';');
console.log(value);

是的,eval是邪恶的但 是一种解决方案(尽管这是一项奇怪的任务)。

答案 1 :(得分:2)

你可以用邪恶的eval

来做到这一点
function test() {
 var a = 5;
 var myname = "a";
 console.log(eval(myname))
}

test()

答案 2 :(得分:0)

变量不能成为闭包的“全局” 它要么是全球性的,要么不是全球性的。

如果不是,则它在功能范围内。

如果它在一个函数的范围内,那么获取它的唯一方法是,一旦你在该函数之外,就是将它作为一个属性从函数返回,或者将它附加到一个对象/数组,您传入函数,或创建函数INSIDE函数,返回该变量...

// modifying an object
var my_func = function (obj) {
    var hidden = 1;
    obj.hidden = hidden;
};

var my_obj = {};
my_func(my_obj);
my_obj.hidden; // 1

// returning a function
var my_func = function () {
    var a = 1,
        b = 2,
        c = 3,

        get_a = function () { return a; },
        get_b = function () { return b; },
        get_c = function () { return c; };


    return { a : get_a, b : get_b, c : get_c };
};


var my_obj = my_func();
my_obj.a(); // 1
my_obj.b(); // 2
my_obj.c(); // 3

如果您希望通过“name”执行此操作,那么您将在闭包中创建一个对象,并且您将创建一个函数,该函数接受一个字符串并按名称查找该对象的属性。

// get property by name

var my_func = function () {
    var properties = {
        a : 1,
        b : 2,
        c : 3
    };


    return {
        get : function (name) {
            return properties[name]; // returns undefined if it doesn't exist
        }
    }; 
};


var my_obj = my_func();
my_obj.get("a"); // 1
my_obj.get("b"); // 2

现在你可以。

PS:eval();并不总是保证以上述方式工作 例如,将来eval应该在自己的范围内运行,并且无法访问调用函数的范围(与构建new Function("...");的方式相同)。

修改

为了更进一步,更好地回答有关范围的"global"的问题:

window.bob = "Bob";

var outer_A = function () {
        var mid_A = function () {
            var inner_A = function () {
                console.log("INNER-A");
                console.log("bob = "  + bob );
                console.log("doug = " + doug);
            };

            inner_A();
        };

        mid_A();
    },

    outer_B = function () {
        var mid_B = function () {
                var doug = "Doug",

                    inner_B = function () {
                        console.log("INNER-B");
                        console.log("bob = "  + bob );
                        console.log("doug = " + doug);
                    };

                inner_B();
            },

            mid_C = function () {
                var inner_C = function () {
                    console.log("INNER-C");
                    console.log("bob = "  + bob );
                    console.log("doug = " + doug);
                };

                inner_C();
            };

        mid_B();
        mid_C();
    };


outer_A();
outer_B();

这对你有什么影响?
你应该得到一个看起来像这样的打印输出:

/*

INNER-A
bob = Bob
doug = undefined

INNER-B
bob = Bob
doug = Doug

INNER-C
bob = Bob
doug = undefined

*/

为什么你最终会这样? 嗯,非常简单,因为你有分支功能范围 doug内定义了mid_Bmid_B内创建的任何功能都可能会访问dougmid_B之外创建的任何功能都无法访问doug

当要求inner_C记录doug时,首先检查doug是否存在于自己的功能中。
如果没有,则检查它是否存在于其父函数范围内(mid_C) 如果没有,则检查它是否存在于 父级的功能范围(outer_B)中。 如果没有,则检查它是否存在于 父级的功能范围(window)中。 如果你一直回到window,它就没有父函数范围......
...如果它甚至不在window中,则将值设置为undefined

同时,inner_B找不到doug,因此会检查mid_B并找到doug

这不会使doug“全球化” 它使它成为in-scope

“global”将是outer_Amid_Ainner_Aouter_Bmid_Binner_Bmid_C并且inner_C都可以访问...

......那将是bob bob是全球性的。

它是全局的,因为它附加到窗口对象(或在var中定义为global-scope,除了使用delete时,其工作方式几乎相同。
并且因为所有子函数都具有返回window的函数作用域,所有函数都可以访问被定义为window的属性/ var的任何内容(除非在作用域链上有一个相同的变量)名称,此时它会选择它命中的第一个。

这是global的含义,以及为什么doug在此示例中不是global变量。