简体   繁体   中英

Recursion in javascript

I am trying to understand how the recursion works. The code below walks through the nodes of the HTML document. It invokes a function, passing it each node in turn. can someone please explain how it is being done in steps? thanks.

var walk_the_DOM = function walk(node, func) {
    func(node);
    node = node.firstChild;
    while (node) {
        walk(node, func);
        node = node.nextSibling;
    }
}

The first statement is the function definition:

var walk_the_DOM = function walk(node, func) {
    ...
};

This assigns a function to walk_the_DOM . This function takes in two parameters: node , and func . node is the node you want to work on and func is the function you want to apply on node .

The first line of the function is func(node); . This essentially means you are applying a passed-in function on node . For example, if you called walk_the_DOM like this:

walk_the_DOM(root, function(node) {
    console.log(node);
});

You would be calling

function(node) {
    console.log(node);
}

on every node, which as the effect of printing out every node in the tree.

The next line node = node.firstChild; basically reassigns the node to its first child. The reason you need to do this is because you need to look at each child of the current node. Of course, you also need to look at the children of those children, but we'll get to that part later.

Now we get to the while loop. The condition on this while loop is just while(node) , which just means that the loop will run as long as node is not null or undefined. In our previous statement we did node = node.firstChild . What if the current node has no children? Then node.firstChild will be null and so we won't even enter the loop. We will fall out of it and exit the function ( remember this part; we exit the function if the current node has no children. This is know as the stopping condition of our recursive function ).

Now inside the while loop, we make our recursive call: walk(node, func); . Let's ignore what happens here for a second and move onto the next line: node = node.nextSibling; . Here we're assigning the next sibling of the node back into the variable node . In effect we are iterating over the siblings of this node. Now what if the node has no other sibling (ie, the parent node only has one child)? Then node will be null and we will fall out of the loop.

Now let's get back to the recursive call walk(node, func) . In the recursive call we call the function itself, which means that the behavior of the function is exactly the same as it was for this iteration. You might think at this point "But doesn't that mean that this will execute forever?". But it won't! Why? Remember the stopping condition I mentioned earlier? At some point you will pass in a node that has no children which means that the recursive call will exit and come back to the next line ( node = node.nextSibling ) and execution will proceed normally. Now if you think of the DOM as a tree (which it is), what this means is that you will travel as far down one branch as you can and once you reach the end, you fall back up one level, and check to see if there are any other siblings. If there are, you go down that branch as far as you can go. If not, you fall back up one more level and do the check again. In this way, you are able to traverse the entire DOM tree.

what this code does is it executes the func function on every element of a subtree.

You pass a node into the walk function. it takes all the children of that node, and calls the walk method on them.

every node can be seen as though it were a sub-tree, and each invocation of the walk function just solves a smaller sub-tree solution. since it just walks it doesn't actually do anything.

eventually node.firstChild will be null and since null is compared to false in javascript, it will just not enter the loop.

// 1. you define a function
var walk_the_DOM = function walk(node, func) { 

    // 4. you call your callback
    func(node);
    // func.call(node); // inside func, 'this' will be node

    // 5. you get the first child
    node = node.firstChild;

    // 6. as long as 'node' is, so not false, 0, null, undefined or '',
    while (node) {

        // 7. recurse the function, jumps to step 4 (in a new closure of walk)
        walk(node, func);
        // walk_the_DOM(node, func);

        // 8. get the next child, going to step 6
        node = node.nextSibling;
    }

    // 9. no more siblings, current walk returns

}; // 2. the function is defined, by name 'walk' and in var 'walk_the_DOM'!

// 3. you call the function once, with an anonymous callback
walk(document, function (currentNode) { });
// walk_the_DOM(document, function (currentNode) { });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM