I’m iterating over some api data and mapping the API’s data to Coffeescript objects. What’s puzzling me is why just part of that data disappears between these two console.log statements:
items = (for item in @apiFeedPage.items
fi = new API.FeedItem(item, @apiFeedPage.instance_url)
console.log fi.comments.comments
window.API.itemHash[fi.id] = fi #save for later usage
fi )
console.log items[0].comments.comments
In the above, the first console.log outputs the comments I expect: fi.comments.comments is equal to an array of Comment objects (Comments are a property on a FeedItem) In the second console.log statement, the comments objects are there but are not assigned – as if the Comment constructor was run on a API response with no comments.
The constructor looks like this:
class API.FeedItem extends API.FeedComponent
# instance vars
comments: {}
constructor: (data, instance_url) ->
super(data, instance_url)
@parent = new API.User( data.parent )
@comments.comments = (new API.Comment(api_comment) for api_comment in data.comments.comments)
@comments.total = data.comments.total
@comments.nextPageUrl = data.comments.nextPageUrl
And I’ve confirmed that inside the constructor, the @comments.comments is properly assigned, which is what you’d expect since the first console.log statement has the expected objects. The first block of code above sits in a Ajax callback function using a fat arrow, so my initial suspicion that this had to do with losing the context of “this” doesn’t seem to apply, and since all the other expected data inside FeedItem is there…
Any ideas on why the items[0].comments.comments is equal to [] in the second statement?
I would guess that the last
data.comments.commentsinside yourAPI.FeedItemconstructor is empty. That would cause@comments.commentsto be[]. But then you’d ask:The answer is simple, this:
creates a single
comments = { }object that is attached to theAPI.FeedItemprototype and thus is shared by all instances ofAPI.FeedItem; in other words, the comment is a lie, that’s not an instance variable.Consider this simplified analogue to your situation:
You’re probably expecting to see
[1],[1,2],[1,2,3],[1,2,3,4]come out but you’ll see four identical[1,2,3,4]s instead: http://jsfiddle.net/ambiguous/hf9zL/If you fix your class to initialize
@commentsper instance:Then you’ll see the
[1],[1,2],[1,2,3],[1,2,3,4]that you’re expecting.You could even throw a
in to see that the arrays are, in fact, the same array; the extra
[1] == [1]comparison is to prove to you that==is actually comparing the objects rather than their content (i.e. CoffeeScript’s==is JavaScript’s===).A rule of thumb: don’t try to define instance variables in the class definition, define them in the constructor.