在循环中,I'm附加了一个标记,提醒循环索引计数.为什么它总是提醒循环的最后一个索引

In a loop I'm appending a tag that alerts the loop index count. Why does it always alert the last index of the loop?

本文关键字:循环 索引 最后一个 一个 为什么      更新时间:2023-09-26

为了方便起见,这里有我的代码的交互式jsfiddle版本。以下是违规代码:

for i in [1, 2, 3, 4, 5, 6, 7, 8]
  console.log "cell #{i} was created!"
  cell = $('<div class="inventory-cell"></div>').mousedown (event) ->
    alert "#{i} was clicked!"
  $("#inventory-grid").append(cell)

这是html:

<div id="inventory-dialog" class="dialog">    
    <div id="inventory-grid"></div>    
</div>

以下是它应该如何工作。这将在一个循环中生成一堆单元格。如果我点击第一个我想提醒它的,"1被点击了!"当我点击最后一个时,我想让它说,"8被点击了。"但出于某种原因,我点击的每一个都说,"八被点击了"。为什么会发生这种情况?

所有回调在其主体中引用相同的i变量,在调用任何回调时,该变量的值都将为8

您需要为每个特定回调创建一个本地变量,该变量保存创建回调时i

(function(j) {
    var cell = $('<div class="inventory-cell"></div>').mousedown(function(event) {
        alert("#{j} was clicked!");
    });
    $("#inventory-grid").append(cell);
})(i);

功能等效的CoffeeScript是:

do (i) ->
  cell = $('<div class="inventory-cell"></div>').mousedown (event) ->
    alert "#{i} was clicked!"
  $("#inventory-grid").append(cell)

唯一的区别是do将阴影i,而不是创建一个新的变量,但结果是相同的。

准确的翻译是:

do (j = i) ->
  cell = $('<div class="inventory-cell"></div>').mousedown (event) ->
    alert "#{j} was clicked!"
  $("#inventory-grid").append(cell)
for i in [1, 2, 3, 4, 5, 6, 7, 8]
    do (i) ->
        console.log "cell #{i} was created!"
        cell = $('<div class="inventory-cell"></div>').mousedown (event) ->
            alert "#{i} was clicked!"
        $("#inventory-grid").append(cell)

Fiddle。

您已经在使用jQuery,并且由于for in loops不应该在数组上使用(cofeeScript很糟糕,而且显然重命名了本地javascript),因此您可以避免$.each的闭包问题,如下所示:

$.each([1, 2, 3, 4, 5, 6, 7, 8], function(_,i) {
    var cell = $('<div />', {
        'class': 'inventory-cell',
         on    : {
                  click: function() { alert('#{'+i+'} was clicked!'); }
                 }
    });
    $("#inventory-grid").append(cell);
});

FIDDLE

这两个Coffeescript迭代生成相同的Javascript函数。他们只是以不同的方式对其进行迭代。一个使用for (var i=0 ...),另一个$.each()

for i in [1..8]
  do (i) ->
    console.log "cell #{i} was created!"
    cell = $('<div class="inventory-cell"></div>').mousedown (event) ->
      alert "#{i} was clicked!"
    $("#inventory-grid").append(cell)
    return
$.each([1..8], (_,i)->
    console.log "cell #{i} was created!"
    cell = $('<div class="inventory-cell"></div>').mousedown (event) ->
      alert "#{i} was clicked!"
    $("#inventory-grid").append(cell)
    return
    )

也可以使用原生Javascript数组迭代:

[1..8].forEach (i)->

另一种Javascript迭代方法:

for (i in [1,2,3..]) {}

如果不小心本地化cell定义中使用的i,则会出现与原始Coffeescription相同的问题。

不知道coffeescript。。。或者不知道为什么CCD_ 11在fsfiddle中出错。。

for(var i=1; i<9;i++){
console.log("cell "+ i + "was created!")
~function(i){
    var cell = $('<div class="inventory-cell"></div>').mousedown(function(){
    alert(i+" was clicked!")
    });
  $("#inventory-grid").append(cell)
}(i);
}