你将会有一个非常常见的闭包问题 https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Working_with_Closures#Creating_closures_in_loops.3a_A_common_mistake in the for in
loop.
封闭在闭包中的变量共享同一个环境,所以到了mouseenter
回调被调用,循环将运行它的过程并且id
变量将指向最后一个元素的值names
array.
如果您不熟悉闭包的工作原理,这可能是一个相当棘手的话题。您可能需要查看以下文章以获取简要介绍:
- Mozilla 开发中心:使用闭包 https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Working_with_Closures
您可以使用函数工厂通过更多闭包来解决此问题:
function makeMouseEnterCallback (id) {
return function() {
console.log(id);
};
}
// ...
var id, k,
names = ['one','two','three'];
for (k = 0; k < names.length; k++) {
id = names[k];
$("#" + id).mouseenter(makeMouseEnterCallback(id));
}
您还可以按如下方式内联上述函数工厂:
var id, k,
names = ['one','two','three'];
for (k = 0; k < names.length; k++) {
id = names[k];
$("#" + id).mouseenter((function (p_id) {
return function() {
console.log(p_id);
};
})(id));
}
任何另一种解决方案都可以是@d.m 在另一个答案中建议 https://stackoverflow.com/questions/3287500/why-arent-these-two-bits-of-javascript-equivalent-jquery/3287561#3287561,将每个迭代包含在其自己的范围内:
var k,
names = ['one','two','three'];
for (k = 0; k < names.length; k++) {
(function() {
var id = names[k];
$("#" + id).mouseenter(function () { console.log(id) });
})();
}
虽然与此问题无关,但通常建议避免使用for in
循环迭代数组的项目,如@CMS https://stackoverflow.com/users/5445/cms在下面的评论中指出(进一步阅读 https://stackoverflow.com/questions/3010840/loop-through-array-in-javascript)。此外,在 JavaScript 中,用分号显式终止语句也被认为是一种很好的做法。