Reputation: 189
I'm reading this this example and I'm stuck at understanding one line. I need to understand everything so I can't move on.
This function is supposed to hide all the elements inside an object. It's supposed to work. But to me, that for loop looks like an infinite one. Why is it not?
getChild: function (i) {
return this.children[i];
},
hide: function () {
for (var node, i = 0; node = this.getChild(i); i++) {
node.hide();
}
this.element.hide(0);
},
From what I see, the function takes the first element of the object with getChild(0) and then calls hide again on that 0-dimension object. Then it resets the counter (i) and gets the first element of the 0-dimension object (which is the same 0-dim object) and calls the function again.
I know I'm mistaken but that's what I see. Please show me the light! Thanks
Upvotes: 2
Views: 168
Reputation: 134257
If there is no child at i
, getChild
will return undefined
and break out of the loop.
Consider the following text from the article:
Now create the GalleryImage class. Notice that it uses all of the exact same methods as the GalleryComposite. In other words, they implement the same interface, except that the image is a leaf so it doesn't actually do anything for the methods regarding children, as it cannot have any. Using the same interface is required for the composite to work because a composite element doesn't know whether it's adding another composite element or a leaf, so if it tries to call these methods on its children, it needs to work without any errors.
And consider the constructor for GalleryImage
:
var GalleryImage = function (src, id) {
this.children = [];
this.element = $('<img />')
.attr('id', id)
.attr('src', src);
}
And how the images and composites are constructed:
var container = new GalleryComposite('', 'allgalleries');
var gallery1 = new GalleryComposite('Gallery 1', 'gallery1');
var gallery2 = new GalleryComposite('Gallery 2', 'gallery2');
var image1 = new GalleryImage('image1.jpg', 'img1');
var image2 = new GalleryImage('image2.jpg', 'img2');
var image3 = new GalleryImage('image3.jpg', 'img3');
var image4 = new GalleryImage('image4.jpg', 'img4');
gallery1.add(image1);
gallery1.add(image2);
gallery2.add(image3);
gallery2.add(image4);
container.add(gallery1);
container.add(gallery2);
Since an image cannot contain children, its this.children
will remain an empty array. So, when the hide
function finally gets called on an image (at one of the leaves of the composite tree), the loop will attempt to evaluate this.children[0]
which will return undefined
. This will cause the code node = this.getChild(i)
to evaluate to a "false" value, and that particular for
loop will terminate. Thus preventing an endless loop.
Upvotes: 0
Reputation: 96845
The variable i
is not reset on each iteration. The only actions that are recurisvely executed are the boolean expression and i++
. node.hide()
is not the same as this.hide()
. The latter is a different function being called. If it were the same function, then yes, there would be an infinite loop.
The "outer" hide function is being used to "hide" all the elements in this.getChild(i)
. node.hide()
will call the hide()
method on those elements so they are hidden. There is no infinite loop because node.hide()
, although it has the same name as the function it's being used in, is not the same function.
Upvotes: 2
Reputation: 3022
The code
node.hide();
is still a member of the tree and still traversable. It is just hidden from being displayed.
The initialization part of the for loop
var node, i=0
is executed only once, before the looping begins.
The conditional
node = this.getChild(i)
evaluates to true (non-null) when there is a child node, and false (null) when it has run out of descendants, thereby breaking out of the loop.
Upvotes: 0
Reputation: 39522
In a for
loop like the one above, the first bit (var node, i = 0
) is only executed once, at the beginning of the loop. The loop stops executing when the middle section (node = this.getChild(i);
) returns false. getChild
will return false when there isn't anything at index i
. (Technically, it'll return undefined
, but that equates to false
in this instance).
Secondly, even though hide()
is called in the for loop, i
is not reset. Why? This recursive call creates a new instance of hide()
separate from the original. All of the variables in this new hide()
are separate from the original. (and so on, down the rabbit hole).
See http://www.tizag.com/javascriptT/javascriptfor.php for more information on for loops.
Upvotes: 7