为什么胖箭不会在循环理解中绑定到当前环境?

时间:2013-03-03 10:04:57

标签: javascript loops binding coffeescript list-comprehension

如果我编译这个CoffeeScript:

    funcs = ((=> console.log i) for i in [0..2])                                                                                                                                                                                          

    funcs[0]()  // Prints 3
    funcs[1]()  // Prints 3
    funcs[2]()  // Prints 3

它产生了这个JavaScript:

    (function() {
      var funcs, i;

      funcs = (function() {
        var _i, _results,
          _this = this;
        _results = [];
        for (i = _i = 0; _i <= 3; i = ++_i) {
          _results.push(function() {
            return console.log(i);
          });
        }
        return _results;
      }).call(this);

      funcs[0]();

      funcs[1]();

      funcs[2]();

      funcs[3]();

    }).call(this);

我认为它会改为:

          _results.push((function(i) {
             return function() {
              return console.log(i);
          }})(i));

有人可以解释为什么不这样做吗?

4 个答案:

答案 0 :(得分:1)

胖箭头在词汇上绑定this,而不是每个变量。 使用do使用IIFE捕获变量。

funcs =
  for i in [0..2]
    do (i) ->
      -> console.log i

答案 1 :(得分:0)

这不是闭包的工作方式。从另一个函数范围返回函数时会得到一个闭包:

var closure = (function(i) {
    return function() {
        console.log(i);
    };
})(i);

这可以通过这个丑陋的CoffeeScript来实现(这里不需要胖箭头):

funcs = ((do (j=i) -> -> console.log j) for i in [0..2])

我建议不要把它写成一行。

答案 2 :(得分:0)

好的,所以在查看CoffeeScript文档之后,我相信我已经回答了我自己的问题。 =>仅将函数绑定到this的当前值。我错误地认为它将所有变量绑定到它们的当前值。

......虽然它有一个像这样的功能会很整洁。也许->>

答案 3 :(得分:0)

当您将咖啡转换为javascript时,您将获得一个绑定范围的函数。问题是:

funcs = (function() {
    var _i, _results,
      _this = this;
    _results = [];
    for (i = _i = 0; _i <= 3; i = ++_i) {
      _results.push(function() {
        return console.log(i);
      });
    }
    return _results;
  }).call(this);

在那里,变量i被绑定,但是当你调用函数时,值为3,并且每次调用函数时都保持为3。