JavaScript闭包.循环访问当前i,j变量

JavaScript closures. Access in loop to current i, j variables

本文关键字:变量 闭包 循环 访问 JavaScript      更新时间:2023-09-26

我试图用jQuery动态生成<table>,我想为每个单元格设置点击处理程序,所以当单元格点击时,弹出窗口将显示单元格的当前索引。如何访问循环中的CURRENT ij变量?

  for(var i = 0; i < 5; i++) {
      var tr = $('<tr></tr>');
      for (var j = 0; j < 5; j++) {
          var td = $('<td></td>');
          td.click(function() {
            alert(i + ' ' + j);  // here I want to access to CURRENT i, j variables
          })
          td.appendTo(tr);
      }
  }    

其他答案主要解释了如何解决闭包问题,尽管这些方法并不是特别有内存效率,因为它们最终会为ij的每个可能组合创建一个新的闭包。

然而,由于您使用的是jQuery,您还有许多其他选项可供选择:

data参数传递给.on调用

td.on('click', { i: i, j: j }, function(event) {
    var i = event.data.i;
    var j = event.data.j;
    alert(i + ' ' + j);
});

您可以在上面看到的ij值将在event.data 中可用

使用$.each而不是for进行迭代

$.each(Array(5), function(i) {
    // i is already bound here because it's a function parameter
    $.each(Array(5), function(j) {
        // and j available here
        td.on('click', ...);
    });
});

使用事件委派而不是每个元素的处理程序

$('#myTable').on('click', 'td', function() {
    // use jQuery methods to determine the index, e.g.
    var j = this.cellIndex
    var i = this.parentNode.rowIndex
    ...
});

这比单独地将单独的处理程序绑定到每个CCD_ 13更有效。

更一般地,使用.data()来存储每个小区的信息

您可以将数据值直接存储在元素上,如果您想检索单元格和行索引以外的值,这将非常有效:

td = $('<td>').data({i: i, j: j});

然后直接从点击的元素的.data:中提取这些行和列值

for (var i = 0; i < 5; i++) {
    var tr = $('<tr></tr>');
    for (var j = 0; j < 5; j++) {
        $('<td></td>').data({i: i, j: j}).appendTo(tr);
        td.appendTo(tr);
    }
}
$('#myTable').on('click', 'td', function() {
    var data = $(this).data();
    var i = data.i;
    var j = data.j;
    alert(i + ' ' + j);
});

将它们引入一个新的范围将捕获它们的当前值:

(function(i, j) {
    td.click(function() {
        alert(i + ' ' + j);  // here I want to access to CURRENT i, j variables
    });
})(i, j);

通过在循环中执行类似的函数,可以为(i, j)的"当前"值创建一个新的作用域

td.click((function (i, j) {
    return function (event) {
        console.log(i, j);
    }
})(i, j));

您可以使用Function.prototype.bind 使其更加简洁

td.click(function(i, j, event){
  console.log(i, j);
}.bind(td, i, j));

注意.bind解决方案需要ECMAScript 5,因此如果您想支持较旧的浏览器,请查看es5填充


请参阅此演示

其他选项可以在元素中存储数据。

  for(var i = 0; i < 5; i++)
  {
      var tr = $('<tr></tr>');
      for (var j = 0; j < 5; j++) 
      {
          var td = $('<td></td>');
          this.data("position",{row:i, column:j});
          td.click(function() 
          {
            var position = this.data("position");
            alert(position.row + ' ' + position.column);  // here I want to access to CURRENT i, j variables
          })
          td.appendTo(tr);
      }
  } 

我会将索引存储为属性,并向表中添加一个单击处理程序:

var tableHtml = '';
for(var i=0; i<5; i++) {
    tableHtml += '<tr>';
    for (var j=0; j<5; j++) {
        tableHtml += '<td data-i="' + i + '" data-j="' + j + '"></td>';
    }
    tableHtml += '</tr>';
}
$('table').append(tableHtml).on('click', 'td', function(ev) {
    var i = this.getAttribute('data-i'),
        j = this.getAttribute('data-j');
});