bizzare undefined变量

时间:2012-07-12 00:51:55

标签: javascript jquery coffeescript

我有一个包含对象的多维数组,如果它们包含特定属性,我希望从数组中删除它们。

的CoffeeScript

for dataColumn in allDataColumns
    for brentSpiner, i in dataColumn
        console.log i, brentSpiner.refreshRate
        #dataColumn.remove i if brentSpiner.refreshRate is -1

上面的console.log按预期工作,当下面的行被注释掉时

for dataColumn in allDataColumns
    for brentSpiner, i in dataColumn
        console.log i, brentSpiner.refreshRate
        dataColumn.remove i if brentSpiner.refreshRate is -1

上述错误如下:brentSpiner is undefined console.log(i, brentSpiner.refreshRate);在firebug中

第二行的存在如何导致上一行中的变量变得不确定?

RENDERED JAVASCRIPT

失败

for (_i = 0, _len = allDataColumns.length; _i < _len; _i++) {
  dataColumn = allDataColumns[_i];
  for (i = _j = 0, _len1 = dataColumn.length; _j < _len1; i = ++_j) {
    brentSpiner = dataColumn[i];
    console.log(i, brentSpiner.refreshRate);
    if (brentSpiner.refreshRate === -1) {
      dataColumn.remove(i);
    }
  }
}

作品

for (_i = 0, _len = allDataColumns.length; _i < _len; _i++) {
  dataColumn = allDataColumns[_i];
  for (i = _j = 0, _len1 = dataColumn.length; _j < _len1; i = ++_j) {
    brentSpiner = dataColumn[i];
    console.log(i, brentSpiner.refreshRate);
  }
}

(旁注:.remove已通过Resig添加到Array原型中)

更新

这是我的逻辑错误。查看已批准的答案以了解原因。贝娄是我最终做的并且运作良好:

for dataColumn in allDataColumns
    i = 0
    len = dataColumn.length
    while i < len
        if dataColumn[i].refreshRate is -1
            dataColumn.remove i
            len--
        i++

渲染

for (_i = 0, _len = allDataColumns.length; _i < _len; _i++) {
  dataColumn = allDataColumns[_i];
  i = 0;
  len = dataColumn.length;
  while (i < len) {
    if (dataColumn[i].refreshRate === -1) {
      dataColumn.remove(i);
      len--;
    }
    i++;
  }
}

2 个答案:

答案 0 :(得分:0)

Coffeescript正在“冻结”_len1中列表的长度。删除条目时,您将在内循环中运行列表的末尾。

对我来说看起来像个错误。 (除非有一些语言功能,你应该通知Coffeescript数组长度可能会改变。)

答案 1 :(得分:0)

向循环列表添加/删除元素是一项危险的操作,语言很难自动处理。如果你需要做这样的事情,你应该避免for..in循环并坚持while循环。以下是我编写该代码的方法:

for dataColumn in allDataColumns
    i = 0
    while i < dataColumn.length
        brentSpiner = dataColumn[i]
        console.log i, brentSpiner.refreshRate
        if brentSpiner.refreshRate is -1
            dataColumn.remove i 
            i--
        i++

我还会逐步转换你的代码,这样我们就能看到我是如何到达那里的:

for dataColumn in allDataColumns
    for brentSpiner, i in dataColumn
        console.log i, brentSpiner.refreshRate
        dataColumn.remove i if brentSpiner.refreshRate is -1

首先,我们需要将内循环变为while循环。只要我们的计数器变量小于长度,我们就会循环,并在循环结束时递增计数器。为了保留语法,我们在循环中做的第一件事是设置循环变量brentSpiner

for dataColumn in allDataColumns
    i = 0
    while i < dataColumn.length
        brentSpiner = dataColumn[i]
        console.log i, brentSpiner.refreshRate
        dataColumn.remove i if brentSpiner.refreshRate is -1
        i++

现在,如果我们从列表中删除一个元素,则会出现问题,因为将跳过下一个元素。示例:列表为[1,2,3]i=0。如果我们决定删除i,那么在while循环结束时,我们会[2,3]i=1。我们要查看的下一个项目是3,因此我们跳过了2。为了解决这个问题,我们每次删除当前计数器处或之前的项目时都会减少计数器。

for dataColumn in allDataColumns
    i = 0
    while i < dataColumn.length
        brentSpiner = dataColumn[i]
        console.log i, brentSpiner.refreshRate
        if brentSpiner.refreshRate is -1
            dataColumn.remove i 
            i--
        i++

如果我们还要添加元素,我们必须非常小心。我们可能必须递增计数器,具体取决于元素的插入位置以及是否应在循环中处理。