最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Why doesn't this CoffeeScriptJavaScript set the properties of created object? - Stack Overflow

programmeradmin2浏览0评论

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 piles 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?

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 piles 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?

Share Improve this question edited Mar 29, 2011 at 18:15 Scott Weinstein asked Mar 29, 2011 at 17:45 Scott WeinsteinScott Weinstein 19.1k15 gold badges82 silver badges117 bronze badges 1
  • 1 It does work... it just doesn't do what you wanted it to do. – Thomas Eding Commented Mar 29, 2011 at 18:12
Add a ment  | 

3 Answers 3

Reset to default 6

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./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)

Craig's answer is correct, but an alternative solution is to define your anonymous function as a bound function. In this case, that would let you write

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

The => binds the function to the context in which it's defined, so that this always means the same thing in the function no matter how it's called. It's a very useful technique for callbacks, though in the case of _.each, it's a bit less efficient than passing this in.

You could do the same thing using Underscore by writing

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

but => saves you a lot of typing!

发布评论

评论列表(0)

  1. 暂无评论