Coffeescript for循环中的索引变量(_i)?

Coffeescript for循环中的索引变量(_i)?,coffeescript,undefined-behavior,Coffeescript,Undefined Behavior,请看以下简单代码: eat = (x) -> console.log "nom", x # dog only eats every second cat feast = (cats) -> eat cat for cat in cats when _i % 2 == 0 feast ["tabby cat" "siamese cat" "norwegian forest cat" "feral cat" "american

请看以下简单代码:

eat = (x) -> console.log "nom", x

# dog only eats every second cat
feast = (cats) -> eat cat for cat in cats when _i % 2 == 0

feast ["tabby cat"
       "siamese cat"
       "norwegian forest cat"
       "feral cat"
       "american bobtail"
       "manx"]

似乎_i变量是当前的索引。这是特性、bug还是NaN?我没有听到其他人谈论过这个,所以我想知道是否有什么原因我不应该在我的代码中使用它?

tldr;《咖啡脚本》的作者刚刚告诉我:不要用我

功能、bug还是NaN

这些都不是;这是未定义的行为。您假设_i将是编译JavaScript中用于迭代的变量

你绝对不应该使用_i,或者假设_i将被定义。这是一个实现细节,他们可以随时更改。如果你的循环嵌套在另一个循环中,它也不会是i;它将是_j或_k等

最重要的是,您可以在不依赖底层实现的JavaSript变量的情况下完成这项工作。如果要使用索引循环,只需使用值,在数组中键入:

具体来说,在您的示例中:

feast = (cats) -> eat cat for cat, index in cats when index % 2 == 0

无需猜测或假设Coffeescript的功能。看看编译后的Javascript。从“尝试咖啡脚本”选项卡:

feast = (cats) -> eat cat for cat in cats when _i % 2 == 0
产生

feast = function(cats) {
  var cat, _i, _len, _results;
  _results = [];
  for (_i = 0, _len = cats.length; _i < _len; _i++) {
    cat = cats[_i];
    if (_i % 2 === 0) {
      _results.push(eat(cat));
    }
  }
  return _results;
};
生成几乎相同的JS,不同之处在于索引与_i一起使用或代替_i

这两种方法都有效,但索引让你们的意图对人类更清晰,包括你们未来的自我。正如其他人所说,避免使用未记录的实现特性是一种很好的编程实践,除非您真的需要它们。如果你在做一些有趣的事情,记录下来

array = ['a', 'b', 'c']

console.log(index) for item, index in array # 0, 1, 2
feast = (cats) -> eat cat for cat, index in cats when index % 2 == 0
feast = (cats) -> eat cat for cat in cats when _i % 2 == 0
feast = function(cats) {
  var cat, _i, _len, _results;
  _results = [];
  for (_i = 0, _len = cats.length; _i < _len; _i++) {
    cat = cats[_i];
    if (_i % 2 === 0) {
      _results.push(eat(cat));
    }
  }
  return _results;
};
feast = (cats) -> eat cat for cat, index in cats when index % 2 == 0
feast = function(cats) {
  var cat, index, _i, _len, _results;
  _results = [];
  for (index = _i = 0, _len = cats.length; _i < _len; index = ++_i) {
    cat = cats[index];
    if (index % 2 === 0) {
      _results.push(eat(cat));
    }
  }
  return _results;
};