为什么使用匿名函数的代码不起作用

ant*_*njs 2 javascript

我试图使用匿名函数添加处理程序锚定对象.

我运行此代码,但它不起作用你能解释原因并尝试修复它吗?谢谢:

var obj = document.getElementsByTagName("a");
var items = ["mouseover", "mouseout"];
for (var i = 0; i < items.length; i++) {
    (function() {
        var item = items[i];
        for (var i = 0; i < obj.length; i++) {
            obj[i]["on" + item] = function() {
                alert("thanks for your " + item);
            };      
        }
    })();               
}
Run Code Online (Sandbox Code Playgroud)

pim*_*vdb 7

i被"悬挂"; 换句话说,您的函数正在执行:

var i;
var item; // vars are hoisted to the beginning

item = items[i];
for (i = 0; i < obj.length; i++) {
    obj[i]["on" + item] = function() {
       alert("thanks for your " + item);
    };      
}
Run Code Online (Sandbox Code Playgroud)

因此,iitems[i]不参照外i.相反,iundefined.您应该使用单独的变量名称,例如j内部循环:

for (j = 0; j < obj.length; j++) {
Run Code Online (Sandbox Code Playgroud)

其次,item会改变,因此警报每次都会使用相同的值.为了避免这种情况,您可以使用匿名函数,但其​​中的要点是传递值以使其"冻结":

var obj = document.getElementsByTagName("a");
var items = ["mouseover", "mouseout"];
for (var i = 0; i < items.length; i++) {
    var item = items[i];

    (function(item) {
        for (var j = 0; j < obj.length; j++) {
            obj[j]["on" + item] = function() {
                alert("thanks for your " + item);
            };      
        }
    })(item);               
}
Run Code Online (Sandbox Code Playgroud)

  • @Felix Kling:如果你使用`j`作为内循环,`i`将具有正确的值,因为它没有被提升,所以你可以安全地捕获它. (3认同)
  • 真的....那么你仍然需要"捕获"`item`;)(否则`alert`将为所有处理程序输出相同的内容(至少是每次外循环迭代创建的那些)). (3认同)

Guf*_*ffa 5

原因是您在为变量分配值之前使用变量:

var item = items[i];
Run Code Online (Sandbox Code Playgroud)

变量i是在下一行声明的局部变量,而不是来自surronding范围的变量.变量具有函数范围,因此尽管变量在下一行声明,但它存在于整个函数中.

如果您希望能够从周围范围访问变量,则需要在函数中为变量使用不同的名称.由于历史原因,循环变量通常根据需要命名为i,j,k.

var obj = document.getElementsByTagName("a");
var items = ["mouseover", "mouseout"];
for (var i = 0; i < items.length; i++) {
  (function() {
    var item = items[i];
    for (var j = 0; j < obj.length; j++) {
      obj[j]["on" + item] = function() {
        alert("thanks for your " + item);
      };
    }
  })();               
}
Run Code Online (Sandbox Code Playgroud)