全球closures的目标
JS中有一些非常基本的东西我不确定。 所以我想问一下。
全局对象是window
(或者当然是global
的node.js)。 所以我们可以通过它的名字window[myVariableName]
得到variables的值。
问题是如何用闭包的局部variables来做到这一点?
function myFunction() { // some code here console.log(global_object[myVariableName]); }
当variables是当前闭包的全局variables但不属于window
对象时,甚至可以通过名称获取variables的值。
从我对JS的了解以及它如何工作 – 这是不可能的。
顺便说一下,这是一个非常受欢迎的面试问题,如何通过名称获取variables的值,而且从来没有提到该variables是全局的。
eval('var value = ' + myVariableName + ';'); console.log(value);
是的,eval是邪恶的,但它是一个解决scheme(虽然一个奇怪的任务)。
你可以用邪恶的eval
来做到这一点
function test() { var a = 5; var myname = "a"; console.log(eval(myname)) } test()
variables不能是“全局”到闭包。
这可能是全球性的,或者不是。
如果不是,那么它在function范围内。
如果它在函数的作用域内,那么一旦你不在函数中,唯一的方法就是使它成为你从函数返回的属性,或者把它附加到一个对象/数组中,传递给函数,或者创build函数的INSIDE函数,它返回该variables…
// 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”来实现,那么你需要在闭包中创build一个对象,然后创build一个函数,该函数接受一个string并按名称查找该对象的属性。
// 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
应该在自己的范围内运行,并且无法访问调用函数的作用域(与构buildnew 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 */
你为什么最终呢?
呃,很简单,因为你有分支function范围。
doug
被定义在mid_B
里面。
在mid_B
中创build的任何函数都可能访问道doug
。
mid_B
之外创build的任何functionmid_B
不能访问道doug
。
当inner_C
被要求logging道doug
,首先检查道格是否存在于自己的函数中。
如果不是,则检查它是否存在于其父函数范围( mid_C
)中。
如果不是,那么它检查它是否存在于其父函数范围( outer_B
)中。
如果不是,则检查它是否存在于其父函数作用域( window
)中。
如果你一直回到window
,它没有父function范围…
…所以如果它甚至不在window
,那么将该值设置为undefined
。
同时, inner_B
找不到doug
,所以它检查mid_B
并finddoug
。
这不会使道doug
“全球”。
它使它in-scope
。
如果outer_A
, mid_A
, inner_A
, outer_B
, mid_B
, inner_B
, mid_C
和inner_C
都有访问权限, mid_C
“全局”。
…会是bob
。
bob
是全球性的。
它是全局的,因为它附着在窗口对象上(或者在global-scope
定义为var
,除了使用delete
之外,其工作方式几乎相同)。
因为所有的子函数都有函数范围,所有的函数都可以访问定义为window
属性/ var的任何东西(除非在同一个名字的范围链上有一个variables,第一个命中)。
这就是global
手段,为什么道doug
在这个例子中不是一个global
variables。