bizzare未定义变量

bizzare undefined variable

本文关键字:变量 未定义 bizzare      更新时间:2023-09-26

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

咖啡脚本

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

当下面的行被注释掉时,上述CCD_ 1按预期工作

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

上面的错误是这样的:firebug 中的brentSpiner is undefined console.log(i, brentSpiner.refreshRate);

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

引用的Java脚本

失败

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

Works

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原型中)

更新

这是我的逻辑错误。查看批准的答案以了解原因。Bellow就是我最终所做的,而且效果很好:

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

Coffeescapet正在"冻结"_len1中列表的长度。当您删除一个条目时,您将在内部循环中运行列表的末尾。

在我看来,这是一个错误。(除非有某种语言功能可以通知Coffeescript数组长度可能会更改。)

向正在循环的列表中添加元素/从中删除元素是一项危险的操作,而语言很难自动处理这一问题。如果你需要做这样的事情,你应该避免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循环结束时,我们有console.log0、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++

如果我们也在添加元素,我们就必须非常小心。我们可能需要增加计数器,这取决于元素被插入的位置以及是否应该在循环中处理它。