For the Backbone application I talked about earlier in this blog, I needed a way to organize child views of my main ApplicationView
. At present, the main view contains three child views: HeaderView
, DocumentView
and SidebarView
.
Initially my approach was to use an array. So, I created a property named childViews : []
in my ApplicationView
and added child views as below.
createChildViews : function(){
this.childViews = [];
this.childViews['header'] = new HeaderView();
this.childViews['document'] = new DocumentView();
this.childViews['sidebar'] = new SidebarView();
}
This worked well until I tried to iterate the childViews
array using Underscore's _.each
method. Both native Array.forEach()
and _.each()
failed to iterate through childViews[]
. Later, when I debugged, I found out that childViews.length
was returning 0.
That got me puzzled, as I was clearly adding elements to the array, but the code says the array length was zero. Seriously, JS?
After a couple of minutes of Googling, figured out that, in JavaScript, when you add an element to an Array using named index, it doesn't affect the length property of that array.
For example, have a look at below code:
var myArray = [];
myArray['header'] = 'Element Header';
myArray['document'] = 'Element Document';
alert(myArray.length); // alerts 0
myArray[0] = 'Zeroth element';
alert(myArray.length); // alerts 1
As you can see, when we add elements to myArray
using named indexes, it doesn't affect the array length at all. But, when you add an element using an integer index, the array's length property changes.
So, with that learning, I dumped the arrays and changed my Backbone view code to handle the child views as below:
createChildViews : function(){
this.childViews = {
header : new HeaderView(),
doc : new DocumentView(),
sidebar : new SidebarView()
};
}
iterateChildViews : function(){
_.each(this.childViews, function(childView){
// make sure we are not touching other properties of childViews object.
if(childView instanceof Backbone.View){
// Do something with the view.
}
}, this);
}
With this code, even if I want to access my child views as this.childViews['header']
, I am still be able to do so. And I could iterate my child views as well. Win!
undefined