1

我有一个变量范围问题,我不明白为什么会发生这种情况以及如何摆脱它:

    var items = ['foo', 'bar'];
    for (var index in items) {
        var item = items[index];
        var selector = '.'+item+'-class';
        $(selector).bind('click', function() {
            console.log("class: "+$(this).attr('class'));
            console.log("selector: "+selector);
            console.log("item: "+item);
        });
    }

认为此代码通过以下 HTML 自行执行:

<div class="foo-class">Foo</div>
<div class="bar-class">Bar</div>

单击“Foo”会在第一行回显正确的类(即“foo-class”),但选择器和后面的项目名称与 bar 相关。我认为问题在于循环的第二次迭代重置了第一次迭代中使用的变量。

我认为循环内部的声明应该在这个级别清楚地声明它们的范围。我错了吗 ?为什么 ?我该如何解决?

我不是在寻找解决方法,我想要一些干净的东西,更好地理解 javascript 变量范围机制。

这里是jsfiddle

谢谢 !

4

5 回答 5

4

这是您更新的小提琴示例。

var items = ['foo', 'bar'];
for (var index in items) {
    (function() {
        var item = items[index]; 
        var selector = '.' + item + '-class';
        $(selector).bind('click', function() {
            console.log("class: " + $(this).attr('class'));
            console.log("selector: " + selector);
            console.log("item: " + item);
        });
    })();
}​

创建匿名函数将为您定义的每个变量定义一个新范围

提示:尝试创建一个单独的函数来执行绑定,以保持代码更简洁。

于 2012-04-12T20:58:42.963 回答
1

这些 for 循环总是一样的(google it)。JavaScript 没有块作用域而是函数作用域,因此当单击一个项目时,一个变量selector具有它在最后一次循环运行后的值(对于变量也是如此item)。

为了解决这个问题,您需要在循环中使用另一个闭包,将变量存储在自己的范围内。这意味着您需要为每个循环运行执行一个函数。

于 2012-04-12T20:56:58.493 回答
1

这个问题并不是严格意义上的变量范围。匿名函数在触发点击事件时运行,而不是在您在循环中定义它时运行。考虑以下与您的示例在功能上相同的内容:

var items = ['foo', 'bar'];

for (var index in items) {
    var item = items[index];
    var selector = '.'+item+'-class';
    $(selector).bind( 'click', test );
}
​
function test() {
    console.log("selector: "+selector);
}

这(希望)演示了正在发生的事情:函数中的全局变量selector在调用函数时在两种情况下都是相同的(“bar”)。

于 2012-04-12T21:03:41.197 回答
0
var items = ['foo', 'bar'];
for (var index in items) {
    (function(i){  
    var item = items[i];
    var selector = '.'+item+'-class';
    $(selector).bind('click', function() {
            console.log("class: "+$(this).attr('class'));
            console.log("selector: "+selector);
            console.log("item: "+item);
        });
    })(index);
}

在这里拉小提琴。

于 2012-04-12T21:07:57.627 回答
0

变量“选择器”和“项目”是对您存储值的位置的引用,当您单击其中一个 htl 元素时,这两个值的值是最后一个循环中的一个。

于 2012-04-12T21:09:34.447 回答