3

我正试图解决一个范围问题。举两个例子:

一个)

var sels = ['.a', '.b', '.c'];
while ( (var sel = fieldsets.shift()) !== undefined ) { 
    (function(sel) {
        $(sel).click(function() {
            console.log(sel);
        });
    })(sel);
}

在此示例中,当单击引用的元素之一时,输出将为.a.b.c

b)

var sels = ['.a', '.b', '.c'];
while ( (var sel = fieldsets.shift()) !== undefined ) { 
    $(sel).click(function() {
        console.log(sel);
    });
}

在此示例中,单击将产生undefined

我显然误解了这两个示例中的作用域是如何应用的,因为在我看来,.click在任何一种情况下调用何时都sel不再存在。

这两种情况之间应用范围的方式有什么区别?

4

1 回答 1

3

关键就在你的这份声明中:

...因为正如我所看到的,当在任何一种情况下调用 .click 时, sel 根本不再存在。

在像 C 这样的语言中,这是真的。不是 JavaScript!当一个函数被实例化时(就像在您的两个示例中创建事件处理程序所做的那样),它会“捕获”封闭的上下文。执行函数时,该上下文仍然可用,这与基于堆栈的语言不同。(我们正在谈论“关闭”的主题,您可以在其他地方找到比我在这个简短答案中输入的更清晰的解释。)

关键区别在于您的第一个示例引入了一个新层。在该示例中,每个实例化的事件处理程序有效地获取其自己的私有“sel”变量,该变量是匿名包装函数的参数。由于名称匹配,因此无法访问外部“sel”。

在第二个示例中,因为所有事件处理程序共享对同一个唯一变量“sel”的访问,所以当它们被调用时,它们都看到相同的东西:“sel”的值,就像它在循环结束时一样。该值将是undefined因为那是您的循环停止的时间。

于 2013-05-08T17:10:01.680 回答