0

I guess its to stop browsers getting nailed all the time by duff code but this:

        function print(item) {
            document.getElementById('output').innerHTML = 
               document.getElementById('output').innerHTML
               + item + '<br />';
        }

        function recur(myInt) {
            print(myInt);
            if (int < 10) {
                for (i = 0; i <= 1; i++) {
                    recur(myInt+1);
                }
            }
        }

produces:

0
1
2
3
4
5
6
7
8
9
10
10

and not the big old mess I get when I do:

        function recur(myInt) {
            print(myInt);
            if (int < 10) {
                for (i = 0; i <= 1; i++) {
                    var x = myInt + 1;
                    setTimeout("recur("+x+")");
                }
            }
        }

Am I missing something or is this how you do recursion in JS? I am interested in navigating trees using recursion where you need to call the method for each of the children.

7
  • 1
    if (int < 10) would fail the if block and stop recursing. That's the expected behavior in any language. Commented Sep 2, 2011 at 15:38
  • 1
    Please avoid naming a variable "int". While it may be legal in js, it's confusing because it's a reserved word in many other languages. Commented Sep 2, 2011 at 15:42
  • the two versions of the method should return the same code then, and they don't the second one produces the large amount of numbers as i would expect given that the method calls itself twice. Commented Sep 2, 2011 at 15:42
  • for (i = 0; i <= 1; i++) looks rather pointless to me. Why do you need a loop to iterate exactly twice? Commented Sep 2, 2011 at 15:43
  • 1
    PS. I don't know what you cut out of your answer, but you've reduced it to a pretty weird for clause. Commented Sep 2, 2011 at 15:43

3 Answers 3

4

You are using a global variable as loop counter, that's why it only loops completely for the innermost call. When you return from that call, the counter is already beyond the loop end for all the other loops.

If you make a local variable:

function recur(int) {
    print(int);
    if (int < 10) {
        for (var i = 0; i <= 1; i++) {
            recur(int + 1);
        }
    }
}

The output is the same number of items as when using a timeout. When you use the timeout, the global variable doesn't cause the same problem, because the recursive calls are queued up and executed later, when you have exited out of the loop.

Sign up to request clarification or add additional context in comments.

2 Comments

excellent! thanks! I knew i was missing something... I had the var in there before but for some reason I removed it!
Stupid as I thought when i took the var out that this will put it in the global scope wont it.. ah well i am still learning JS ;-)
2

I know what your doing wrong. Recursion in functions maintains a certain scope, so your iterator (i) is actually increasing in each scope every time the loop runs once.

function recur(int) {
            print(int);
            if (int < 10) {
                for (var i = 0; i <= 1; i++) {
                    recur(int+1);
                }
            }
        }

Note it is now 'var i = 0' this will stop your iterators from over-writing eachother. When you were setting a timeout, it was allowing the first loop to finish running before it ran the rest, it would also be running off the window object, which may remove the closure of the last iterator.

Comments

1

Recursion is very little restricted in JavaScript. Unless your trees are very deep, it should be fine. Most trees, even with millions of elements, are fairly wide, so you get at most log(n) recursive calls on the stack, which isn't noramally a problem. setTimeout is certainly not needed. As in your first example, you're right that sometimes you need a guard clause to guarantee that the recursion bottoms out.

1 Comment

This doesn't deal with the scope problem, which is the root of his difficulty

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.