Javascript范围/关闭:为什么我可以在这里访问内部变量?

时间:2014-01-16 16:36:11

标签: javascript scope closures

我目前正在开展一个相对简单的项目并发现了一些东西:

var test = (function() {
    var internal = 5;
    return {
        init: function() {
            $(document).on('click', function() {
                alert(internal);
            });
        }
    };
}());
test.init();

我认为封闭和javascript范围(正如我所理解的)意味着一个函数只能访问它自己的变量,并且它们高于它的1级。那么为什么这样呢?当我点击文档时,我收到“5”的警报,我希望得到未定义。

这是一个JSFiddle,展示了我正在做的事情:

http://jsfiddle.net/mcraig_brs/m644L/1/

2 个答案:

答案 0 :(得分:4)

  

我认为封闭和javascript范围(正如我所理解的)意味着一个函数只能访问它自己的变量,并且它们高于它的1级。

不,它高于所有级别。事实上,这就是全局变量在JavaScript中的作用;他们只是一个关闭行动的例子。

  

那么为什么这样呢?

当JavaScript引擎需要解析符号时,它首先(松散地)在符号出现的执行上下文中查找(在这种情况下,通过调用您传入的匿名函数创建的那个{{ 1}})。如果它在那里找不到匹配的变量,它会查看围绕该变量的执行上下文(在这种情况下,是通过调用on创建的执行上下文)。如果它没有找到那里,它会查看下一个(通过调用最外面的匿名函数创建的那个)。如果没有,那么下一个级别,直到它到达全局执行上下文。

关于闭包的更多信息(在我的博客上):Closures are not complicated

请注意,我一直在说“......由 ...的调用创建”。这是一个关键点:在程序运行时,可以(几乎总是)为给定的范围创建多个执行上下文。考虑:

init

(这只是两个级别,但它适用于你想要的多个级别。)

调用时,

function foo(name) { return function() { alert(name); }; } 创建并返回一个函数,该函数在调用时向我们显示创建该函数时传递给foo 的名称

foo

调用var f1 = foo("one"); var f2 = foo("two"); f1(); // "one" f2(); // "two" 会创建执行上下文。函数foo创建了一个持久的引用,该引用包含该调用的变量的上下文部分(规范称它为“变量绑定对象”)。 foo返回后,该绑定对象仍然存在,这就是为什么当我们调用函数foo创建时,它仍然可以访问相关的foo变量。

重要的是要记住,闭包不是得到变量的的副本。他们得到持久引用到该变量。这就是为什么这样做的原因:

name

答案 1 :(得分:0)

Javascript是静态范围的。在编写函数时,您可以访问函数内可用的所有变量,因为它们可以从您访问它的位置获得。

var a = 10;
function foo() {
    // now i have access in a
    var b = 20;
    // i have access to both a and b
    function bar() {
        // still have access to both a and b
        var c = 30;
        // any more nested function will have access to a,b and c
    }
}