我有一个可变范围问题,我不明白为什么会发生这种情况以及如何摆脱它:
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。
谢谢!
答案 0 :(得分: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);
});
})();
}
创建匿名函数将为每个已定义的变量定义新范围
提示:尝试创建一个单独的函数来执行绑定,只是为了使代码更清晰。
答案 1 :(得分:1)
这些for循环(google)总是一样的。 JavaScript没有块范围,但是没有函数范围,所以当单击一个项时,一个变量selector
具有它在最后一个循环运行后具有的值(变量{{1}相同) })。
要解决这个问题,你需要在循环中使用另一个闭包,它将变量存储在自己的作用域中。这意味着你需要为每个循环运行执行一个函数。
答案 2 :(得分:1)
问题并不严格关于变量范围。匿名函数在触发click事件时运行, not 在循环中定义时。请考虑以下功能与您的示例相同的内容:
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
在调用函数时在两种情况下都相同(&#34; bar&#34 ;)
答案 3 :(得分: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);
}
答案 4 :(得分:0)
Vars“selector”和“item”是对存储值的位置的引用,当您单击其中一个htl元素时,这两个值的值是最后一个循环的那个。