为什么这个CoffeeScript / JavaScript没有设置创建对象的属性?

时间:2011-03-29 17:45:27

标签: javascript coffeescript

我有以下两个CoffeeScript类定义。我期望他们有相同的行为,但他们没有。特别是在A的实例上访问DoesNotWork未定义。

fields = ["A","B","C"]

class DoesNotWork
  constructor: () ->
    _.each(fields, (f) -> @[f] = ko.observable(''))

class DoesWork
  constructor: () ->
    @A = ko.observable('')
    @B = ko.observable('')
    @C = ko.observable('')

以上代码编译为

var DoesNotWork, DoesWork, fields;
fields = ["A", "B", "C"];
DoesNotWork = (function() {
  function DoesNotWork() {
    _.each(fields, function(f) {
      return this[f] = ko.observable('');
    });
  }
  return DoesNotWork;
})();
DoesWork = (function() {
  function DoesWork() {
    this.A = ko.observable('');
    this.B = ko.observable('');
    this.C = ko.observable('');
  }
  return DoesWork;
})();

我错过了什么新手JS?

3 个答案:

答案 0 :(得分:6)

另一个解决方案(可以说是最具可读性和效率)是跳过_.each而是使用CoffeeScript的for...in迭代:

for f in fields
  @[f] = ko.observable ''

你甚至可以对循环进行后缀以使其成为单行:

@[f] = ko.observable('') for f in fields

请记住,CoffeeScript中的循环不会创建上下文或影响范围;只有功能。

答案 1 :(得分:4)

'this'在传递给_.each的匿名函数中绑定到匿名函数,而不是父对象。 _.each确实允许传递上下文对象,以便通过

正确绑定它

http://documentcloud.github.com/underscore/#each

所以在每个第3个arg中将ref传递给你想要绑定的对象:

class ShouldWorkNow
  constructor: () ->
    _.each(fields, ((f) -> @[f] = ko.observable('')),this)

答案 2 :(得分:3)

Craig的回答是正确的,但另一种解决方案是将您的匿名函数定义为bound function。在这种情况下,这将让你写

_.each(fields, ((f) => @[f] = ko.observable('')))

=>将函数绑定到定义它的上下文,这样this总是意味着函数中的相同内容,无论它如何被调用。对于回调来说,这是一种非常有用的技术,但在_.each的情况下,它比传递this的效率要低一些。

你可以通过编写

来使用Underscore做同样的事情
callback = _.bind ((f) -> @[f] = ko.observable('')), this
_.each(fields, callback)

=>为您节省了大量的打字费用!