Javascript: Get a reference from JSON object with traverse
I need to get a reference from JSON object, the code just following:
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 (i in data) { // console.log(data[i]); if(data[i].pk && data[i].pk == pk) return data[i]; if (typeof(data[i].children) == 'object') this.traverse(data[i].children, pk); }; }, }
The code works very well when traverse the top level items:
>>> Tree.traverse(Tree.data, 1); Object {pk=1}
But broken when get the child element:
>>> Tree.traverse(Tree.data, 22); undefined
I'm very strange why it's this behavior, when you uncomment the '// console.log(data[i]);' line you w开发者_如何学运维ill see the object is got but didn't returned.
Any idea about it ?
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/
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.
精彩评论