【问题标题】:CoffeeScript dynamic methodsCoffeeScript 动态方法
【发布时间】:2011-06-29 03:44:54
【问题描述】:

我正在尝试在咖啡脚本中动态创建方法,但正如我的代码所示,我用来创建方法的迭代器不会在迭代之间重置其变量,因此我遇到了冲突的共享变量:

class MyClass
  constructor: (@name) ->

  for k, v of ['get', 'set']
    console.log('creating method: ' + v)
    MyClass::[v] = (args...) ->
      method = v
      console.log('executing method: ' + method)

o = new MyClass('dummy')
o.get()
o.set()

输出:

> creating method: get
> creating method: set
> executing method: set
> executing method: set

知道我做错了什么吗?

【问题讨论】:

  • 顺便说一句,您可以改变主意并接受 Trevor 的回答。使用 do 可能比单独的函数更符合习惯。

标签: metaprogramming coffeescript


【解决方案1】:

mu 已正确诊断出问题。最直接的解决方案是使用 CoffeeScript 语言的 do 关键字,它创建并运行一个内部函数,该函数捕获您传入的变量的值:

for k, v of ['get', 'set']
  do (k, v) ->
    console.log('creating method: ' + v)
    MyClass::[v] = (args...) ->
      method = v
      console.log('executing method: ' + method)

我在我的 PragPub 文章 A CoffeeScript Intervention 中谈到了这个功能。

【讨论】:

  • do 是否专门用于关闭关闭?我可以看到它的其他用途,但它闻起来像是专门为这个特定用例添加的。
  • 确实如此。在 1.0 之前,for 循环自动为您捕获变量,但这会产生其他问题(例如,break/continue 不起作用),因此在 1.0 版本之前添加了 do(之前建议) .见issue 959
  • 在任何地方创建自执行闭包也很方便。 do -> somePrivateVar = 'foo'
【解决方案2】:

你的内在功能:

(args...) ->
  method = v
  console.log('executing method: ' + method)

实际上是v 上的闭包,所以当它被执行时,v 将计算为它在循环中的最后一个值(即set)。看起来你只需要一点关闭破坏:

build_method = (v) ->
  (args...) ->
    method = v
    console.log('executing method: ' + method)

然后:

for k, v of ['get', 'set']
  console.log('creating method: ' + v)
  MyClass::[v] = build_method(v)

请记住,CoffeeScript 只是具有不同构成的 JavaScript,因此它存在许多相同的问题(就像任何具有闭包的语言一样)并且这些问题具有相同的解决方案。

【讨论】:

  • 谢谢,它符合你的逻辑。我只在构造函数方法中添加了方法创建来访问类变量和方法。
  • @loophole:这几乎是您在 JavaScript 中所做的相同事情的音译。您只需要使用单独的函数调用在正确的时间强制评估 v
猜你喜欢
  • 2012-02-23
  • 2015-05-16
  • 2012-12-19
  • 1970-01-01
  • 2015-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多