【问题标题】:Javascript Scope/Closure: Why can I access internal vars here?Javascript 范围/闭包:为什么我可以在这里访问内部变量?
【发布时间】:2014-01-16 16:36:10
【问题描述】:

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

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/

【问题讨论】:

  • 我相信变量可以在页面中的任何位置访问..即他们的范围是整个页面
  • 查看net.tutsplus.com/tutorials/javascript-ajax/…了解更多关于闭包如何工作的细节
  • @AlienArrays: internal 未在 test 函数中定义; test 最终引用了匿名函数返回的对象。

标签: javascript scope closures


【解决方案1】:

我认为闭包和 javascript 范围(据我理解)意味着一个函数只能访问它自己的变量,以及它上面的 1 级。

不,它是高于它的所有层。事实上,这就是全局变量在 JavaScript 中的工作方式。它们只是闭包的一个例子。

那么为什么会这样呢?

当 JavaScript 引擎需要解析符号时,它首先(松散地)在符号出现的执行上下文中查找(在这种情况下,由调用您传递给 @987654322 的匿名函数创建的上下文) @)。如果在那里找不到匹配的变量,它会查看围绕该变量的执行上下文(在本例中,是通过调用init 创建的那个)。如果在那里找不到它,它会查看下一个(通过调用最外层匿名函数创建的那个)。如果不存在,则下一级,直到到达全局执行上下文。

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

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

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变量。

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

function foo(a) {
    return function() {
        alert(++a);
    };
}
var f = foo(0);
f(); // 1
f(); // 2
f(); // 3

【讨论】:

    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-01-01
      • 2011-08-23
      • 2011-11-24
      • 2018-09-21
      • 2012-03-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多