I have an issue, that was really hard to notice, because for the most part everything works. It was only when I tried to manipulate my data in my collections initialize function that I found a problem.
The backbone docs at http://backbonejs.org/#Collection-constructor
“If you define an initialize function, it will be invoked when the collection is created.”
so I interpreted that as, my initialize function won’t run until after my models are set. “That sounds ideal,” said I, but then I ran into this.
My bootstrap code is as follows:
new MyCollection(<?php if ($data) {echo json_encode($data);} ?>);
My collection:
var MyCollection = Backbone.Collection.extend({
model: MyModel,
initialize: function() {
console.log(this);
console.log(this.length);
this.each(function(model) {
console.log(model);
});
}
});
I got strange results.
The first console.log(this); was a collection object as expected:
{
....
models: [3],
length: 3
....
}
and the second console(this.length); printed out the number 0
the console inside this.each() didn’t show up.
What’s happening?
The Collection constructor looks like this:
Step by step:
this._reset()call does athis.length = 0.this.initialize.apply(...)is the call to yourinitializemethod.this.reset(...)will calladdto add the models. Theaddcall will update the collection’smodelsandlengthproperties.So, when
initializeis called, you’ll havethis.length == 0andthis.modelswill be an empty array since only_resetwill have been called here. Now we can easily see whythis.eachdoesn’t do anything and whyconsole.log(this.length)says0.But why does
console.log(this)tell us that we have a populated collection? Well,console.logdoesn’t happen right away, it just grabs references to its arguments and logs something to the console a little bit later; by the timeconsole.loggets around to putting something in the console, you’ll have gotten through (3) above and that means that you’ll have thethis.modelsandthis.lengththat you’re expecting to see. If you sayor:
you’ll see the state of things when
console.logis called rather than the state of things whenconsole.logwrites to the console.The documentation isn’t exactly explicit about what is supposed to be ready when
initializeis called so you’re stuck tracing through the source. This isn’t ideal but at least the Backbone source is clean and straight forward.You’ll notice that
initializeis called like this:The
argumentsin there means thatinitializewill receive the same arguments as the constructor so you could look in there if you wanted: