I've the following two CoffeeScript class definitions. I expected them to the same behavior, but they don't. In particular accessing A on instances of DoesNotWork is undefined.
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('')
the above code compiles to
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;
})();
What newbie JS subtly am I missing?
Yet another solution (arguably the most readable and efficient) is to skip _.each and instead use CoffeeScript's for...in iteration:
for f in fields
@[f] = ko.observable ''
You could even postfix the loop to make it a one-liner:
@[f] = ko.observable('') for f in fields
Remember that loops in CoffeeScript don't create context or affect scope; only functions do.
'this' in the anonymous function passed to _.each is bound to the anonymous function, not the parent object. _.each does allow passing a context object so that this will be bound properly though
http://documentcloud.github.com/underscore/#each
so pass a ref to the object you are trying to bind to in the 3rd arg of each:
class ShouldWorkNow
constructor: () ->
_.each(fields, ((f) -> @[f] = ko.observable('')),this)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With