Coffeescript - 如何应用闭包和匿名函数

Coffeescript - How to apply closure and anonymous functions

我正在尝试将 for 循环变量作为参数传递给 coffeescript 中的 onclick 方法,如下所示:

for index, option_value of @state.option_values
                  dom.span
                    key: "#{index} #{option_value.name}"
                    className: "pull-left col-md-3#{if option_value.selected then ' selected' else ''}"
                    onClick: () => @selectThis option_value


selectThis: (option_value_selected) ->
    alert(option_value_selected.name)

但是option_value总是引用@state.option_valuesoption_value的最后一个值。我知道如何简单地解决这个问题 javascript。但是,如何在咖啡中解决这个问题?

终于找到正确的语法了,感叹:

onClick: @selectThis.bind(null, option_value)

问题是你的函数:

onClick: () => @selectThis option_value

is 只是存储 option_value 引用,直到稍后调用 onClick 处理程序时才会对其进行评估。

这是 JavaScript 和 CoffeeScript 中循环的一个很常见的问题,解决方案总是相同的:在创建匿名函数时强制对变量求值。你的:

@selectThis.bind(null, option_value)

通过调用 Function.prototype.bind 函数来做到这一点(但是当函数被调用时 @ 将是 null 所以要小心)。

JavaScript中一个常见的习惯用法是将循环体变成一个自调用函数:

for(i = 0; i < 6; ++i)
    (function(i) { ... })(i)

强制在每次迭代时评估循环变量。 CoffeeScript 有 do loops 作为这个习语的快捷方式:

When using a JavaScript loop to generate functions, it's common to insert a closure wrapper in order to ensure that loop variables are closed over, and all the generated functions don't just share the final values. CoffeeScript provides the do keyword, which immediately invokes a passed function, forwarding any arguments.

惯用的 CoffeeScript 解决方案如下所示:

for index, option_value of @state.option_values
  do (index, option_value) =>
    dom.span
      key: "#{index} #{option_value.name}"
      className: "pull-left col-md-3#{if option_value.selected then ' selected' else ''}"
      onClick: => @selectThis option_value