我有以下两个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?
答案 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)
但=>
为您节省了大量的打字费用!