4

I have a simple html structure that I need to traverse. For some reason my recursive function returns 'undefined' on any nested nodes, but not for parent nodes. Unfortunately this needs to be native js, no jQuery for this one. Thanks!

HTML:

<div id="container">
  <div id="head"> 
    <span id="left"><</span> 
    <span id="right">></span> 
  </div>
</div>

Script:

var h = hasId(container, 'head');
var l = hasId(container, 'left');
var r = hasId(container, 'right');

console.log(h + " : " + r + " : " + l);
//[object HTMLDivElement] : undefined : undefined

function hasId(ele, id) {
    for (var i = 0; i < ele.childNodes.length; i++) {
        var child = ele.childNodes[i];
        if(child.id == id) return child;
        else hasId(child, id);
    }
}
1

3 Answers 3

15

You are simply the call to return on the recursive call. Also, you should test whether its result is defined. If yes, you can return it, or continue looping if not.

var h = hasId(container, 'head');
var l = hasId(container, 'left');
var r = hasId(container, 'right');

console.log(h + " : " + r + " : " + l);
//[object HTMLDivElement] : undefined : undefined

function hasId(ele, id) {
    for (var i = 0; i < ele.childNodes.length; i++) {
        var child = ele.childNodes[i];
        if(child.id == id) return child;
        else {
          var next = hasId(child, id);
          if(next) return next;
        };
    }
}​
Sign up to request clarification or add additional context in comments.

3 Comments

your code is right, but you've fixed a much more subtle bug without explaining why. It's not just a missing return, as I had originally answered, but the fact that this return only happens if the result of the recursion was itself defined.
You're welcome =) On recursive call, the loop should continue if the result is undefined. So returning it directly doesn't work.
Thanks!!! Worked great...made sense once I read through this example, much appreciated.
6

The else clause should return the value of hasId(child, id), but only if that value is itself defined, otherwise it has to continue through the loop.

Without a return the function will recurse, but not give an answer.

4 Comments

Just putting else return hasId(...) does not work. Pierre's answer, checking that the answer is defined, is correct.
@PaulPhillips I spotted that just now too, but even Pierre's answer is incomplete - it never unwinds the recursion properly.
@PaulPhillips ah, no, Pierre's answer does appear to fix that.
Ha, I didn't actually read it. On the test input @worked gave, it succeeds: jsfiddle
0

You can fix it like this :

var h = hasId(container, 'head');
var l = hasId(container, 'left');
var r = hasId(container, 'right');

console.log(h + " : " + r + " : " + l);

function hasId(ele, id) {
    for (var i = 0; i < ele.childNodes.length; i++) {
        var child = ele.childNodes[i];
        if(child.id == id || (child = hasId(child, id))){
           return child;
        }
    }
    return false;
}

1 Comment

This doesn't work. If the recurring call does not return any element, your function still returns, when it needs to continue iterating through elements.

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.