JavaScript闭包。访问循环到当前的i,j变量

时间:2013-09-01 16:57:35

标签: javascript jquery

我尝试使用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);
      }
  }    

5 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:2)

您可以通过在循环内执行一个函数来为(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-shim


请参阅此demo

答案 2 :(得分:2)

其他答案主要解释了如何解决闭包问题,尽管这些方法的内存效率并不高,因为它们最终会为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);
});

您可以在i

中找到上面显示的jevent.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
    ...
});

比单独将处理程序绑定到每个<td>更有效。

以及更一般地,使用.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);
});

答案 3 :(得分:0)

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

  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);
      }
  } 

答案 4 :(得分:0)

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

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');
});