4

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

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

问题是如何使用闭包的局部变量来做到这一点?

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

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

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

顺便说一句,如何通过变量的名称获取变量的值是一个非常流行的面试问题,并且从未提到变量是全局的:)。

4

3 回答 3

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

是的, eval 是邪恶的,但它一个解决方案(虽然是一个奇怪的任务)。

于 2013-03-27T20:32:33.957 回答
2

你可以用所有的邪恶来做到这一点eval

function test() {
 var a = 5;
 var myname = "a";
 console.log(eval(myname))
}

test()
于 2013-03-27T20:33:50.113 回答
0

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

如果不是,那么它在函数范围内。

如果它在函数的范围内,那么在该函数之外获取它的唯一方法是将其设置为从函数返回的属性,或者将其附加到对象/数组中传递给函数,或者在函数内部创建一个函数,返回该变量...

// 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

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

// 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_B
在其中创建的任何函数都mid_B可以潜在地访问doug.
在外部创建的任何函数都mid_B不能访问doug

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

同时,inner_B找不到doug,所以它检查mid_B并找到doug

这不会使doug“全球”。
它成功了in-scope

“全球”将是如果outer_A, mid_A, inner_A, outer_B, mid_B, inner_B,mid_C并且inner_C所有人都可以访问...

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

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

这就是global意思,为什么在这个例子doug中不是变量。global

于 2013-03-27T20:45:47.887 回答