+4  A: 

You didn't put return before this.traverse(data[i].children, pk);.


EDIT:

var Tree = {
    data: {
        0: {
            pk: 1,
        },
        1: {
            pk: 2,
        },
        2: {
            pk: 3,
            children: {
                0: {
                    pk: 11,
                },
                1: {
                    pk: 22,
                },
                2: {
                    pk: 33,
                },
            },
        },
    },

    traverse: function(data, pk) {
        for (var i in data) {
            // console.log(data[i]);
            if(data[i].pk && data[i].pk == pk)
                return data[i];

            if (typeof(data[i].children) == 'object') {
                var retVal = this.traverse(data[i].children, pk);
                if (typeof retVal!='undefined') {//here was the logical problem,there might be more than one
                                                 //object, we can't return the result of traversing first one.
                                                 //So we will check, if no return, we go on searching
                    return retVal;
                }
            }

        };
    },
};

alert(Tree.traverse(Tree.data, 1).pk);
alert(Tree.traverse(Tree.data, 22).pk);

check live here: http://jsfiddle.net/rq4LK/

aularon
Could you give me the full sample code ? I tried but didn't make effect.
K K
@K K, I edited it, check the changes, it has a comment to clarify the issue.
aularon
@aularon, Thank you, it seems works fine for me. :-)
K K
@K K, you are welcome : ) and don't forget to mark the answer as accepted.
aularon
@aularon, yeah. :-)
K K
A: 

This is a long shot, but you are creating a global variable in your for loop. Try for(var i in data) instead and then report back please.

In case this is not the whole object and you have a property with a key (like 3: ...) in the parent Object literal that does not exist in the children child property, it will obviously return undefined, as there is no such property by that key.

Edit: As per your comment, this might also be a problem with function scope as you are using tail recursion to iterate over an object with multiple layers. Thus, try to put the current object reference outside the function scope as you would do in any javascript language construct that requires a dynamic reference:

var current = null , match = null ;

function traverse() {

    var data = arguments[0] ;
    var pk = arguments[1] ;

        for(var i in data) {

                current = data[i] ; /* DEBUG */console.log( current.toSource() ) ; //!! Object.prototype.toSource() requires a W3 compatible browser (like FF)

                if(current.pk !== undefined && current.pk === pk) return current ;
                else if( typeof current.children === "object") traverse(current.children, pk);

         }
}

match = traverse(data,pk) ;

Edit 2: Flawed logic on my part. Try this instead:

var match = null ;

function traverse() {

    var data = arguments[0] ;
    var pk = arguments[1] ;

    var current = null ;

        for(var i in data) {

                current = data[i] ; /* DEBUG */console.log( current.toSource() ) ; //!! Object.prototype.toSource() requires a W3 compatible browser (like FF)

                if(current.pk !== undefined && current.pk === pk) match = current ; //!! if there is a match set the variable match to the current object
                else if( typeof current.children === "object") traverse(current.children, pk); //!! else use recursion to test a child property if present

         }

}

Using that, if your object contains the specified property match won't be null and will contain the matching object or child object.

FK82
I tried <code>for (var i in data)</code> but doesn't work, it still response <code>undefined</code>. For your 2nd section: I think the data is a reference here(It same as point in C language). When <code>this.traverse(data[i].children, pk);</code> it's pointed to the 2nd level of the tree.But thank you for your response all the same.
K K
@FK82, Thank you very much, I have a most same idea this morning but haven't tried yet. :-)
K K
No worries, pleasure to be able to help out. :-)
FK82