Reputation: 3657
For example, here is an object I'd like to get a property's value from:
var originalCookieObject = {
User: "[email protected]",
GridStates: {
gridName : {
"page": 1,
"pageSize": 50,
"sort": [
{
field: "CommonName",
dir: "desc"
}
]
}
},
ProtectionState: {
SelectedRow: "string",
PanelsOpen: ['string', 'string']
}
}
And here is how I might retrieve the property's value:
getProperty(originalCookieObject, 'gridName');
I've tried the following recursive function so far:
function traverse(toTraverse, findKey) {
if( typeof toTraverse == "object" ) {
var foundValue = toTraverse[findKey];
if (foundValue){ return foundValue; }
$.each(toTraverse, function(k,v) {
// k is either an array index or object key
traverse(v, findKey);
});
}
}
var objectValue = traverse(originalCookieObject, 'gridName');
console.log(objectValue);
My issue is when I try to go more than one level deep, that current traverse()
call only returns the property value to the parent traverse()
call.
My questions:
traverse()
call return the property value to the parent traverse()
function?Upvotes: 0
Views: 193
Reputation: 3411
var originalCookieObject = {
User: "[email protected]",
GridStates: {
gridName : {
"page": 1,
"pageSize": 50,
"sort": [
{
field: "CommonName",
dir: "desc"
}
]
}
},
ProtectionState: {
SelectedRow: "string",
PanelsOpen: ['string', 'string']
}
}
function traverse(toTraverse, findKey) {
if( typeof toTraverse == "object" ) {
var foundValue = toTraverse[findKey];
if (foundValue){ return foundValue; }
$.each(toTraverse, function(k,v) {
// k is either an array index or object key
foundValue = traverse(v, findKey) || foundValue;
});
return foundValue;
}
}
var objectValue = traverse(originalCookieObject, 'SelectedRow');
console.log(objectValue);
you were almost there, just needed to assign the result of the nested traverse call to a var and then return it at the end of the function
Upvotes: 1
Reputation: 816472
How could I make a child traverse() call return the property value to the parent traverse() function?
By storing the return value of the "child" call in a variable and return it.
Is there a better way to do this?
You definitely have to traverse the structure recursively. Using for...in
would make it a tiny bit easier since you could directly return from the loop body and don't have to use an intermediate variable.
However, the two issues with your implementation are:
if (foundValue){ ... }
);The following solution takes care of 1. and 2.:
function traverse(toTraverse, findKey) {
if( typeof toTraverse == "object" ) {
if (toTraverse.hasOwnPropert(findKey)) { // does object have this property?
return toTraverse[findKey];
}
var foundValue;
$.each(toTraverse, function(k,v) {
var value = traverse(v, findKey);
if (typeof value !== 'undefined') {
foundValue = value;
return false; // stop looking
}
});
return foundValue;
}
}
See jQuery.each
for more information.
Caveat: This solution still doesn't treat properties with value undefined
properly (e.g. {foo: undefined}
), but that should OK for most cases.
Upvotes: 1
Reputation: 1415
You need to check if there is a return value and then store it in a variable:
function traverse(toTraverse, findKey) {
if( typeof toTraverse == "object" ) {
var foundValue = toTraverse[findKey];
if (foundValue){ return foundValue; }
var returnVal;
$.each(toTraverse, function(k,v) {
// k is either an array index or object key
returnVal = traverse(v, findKey) || returnVal; //set/overwrite the returnVal if there is one
});
return returnVal; //return the value to parent, parent will return it further
}
}
var objectValue = traverse(originalCookieObject, 'gridName');
console.log(objectValue);
So you always return a value, either undefined
or the value itself if it was found. This will keep going until it returns to the top. An actual value will always be used over undefined
.
Upvotes: 1