4

看看这个简单的代码:

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"]

$ coffee a.coffee 
nom tabby cat
nom norwegian forest cat
nom american bobtail

似乎_i变量是当前索引。这是功能、错误还是 NaN?我还没有听到其他人谈论这个,所以我想知道是否有某些原因我不应该在我的代码中使用它?

4

2 回答 2

14

tldr-再次;CoffeeScript 的作者刚刚告诉我我是对的:不要使用_i.

14:29 <jashkenas> You shouldn't use internal variables. 
...
14:42 <meagar> I was hoping something more deeply involved in the language would be able to put some authority behind that opinion 
14:43 <meagar> ... I was basically hoping for an authoritative "don't do that" 
14:44 <jashkenas> you just got it ;) 
14:44 <jashkenas> for item, index in list -- there's your reference to the index. 

tldr; 这充其量是一个未记录的功能,其功能等效的记录功能存在。因此,不应使用它。

您关于“少打字”的论点非常可疑;相比:

for x in [1, 2, 3] when _i % 2 == 0
  console.log "#{_i} -> #{x}"

for x,i in [1, 2, 3] when i % 2 == 0
  console.log "#{i} -> #{x}"

功能、错误还是 NaN?

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

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

最重要的是,您可以在依赖底层实现的 JavaSript 变量的情况下做到这一点。如果要使用索引循环,只需使用for value,key in array

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
于 2013-11-04T04:03:16.070 回答
2

无需猜测或做出假设Coffeescript。只看编译好的Javascript。在“试用 Coffeescript”标签中:

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

生成几乎相同的 JS,不同之处仅在于与 .index一起使用或代替_i.

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

两者都有效,但index让人类(包括你未来的自己)更清楚你的意图。正如其他人所说,避免使用未记录的实现特性是一种很好的编程实践——除非你真的需要它们。如果您正在做一些有趣的事情,请记录下来。

于 2013-11-06T19:47:15.323 回答