patternjavascriptMinor
Javascript Object Placement / String Parsing Method
Viewed 0 times
methodplacementjavascriptparsingobjectstring
Problem
This JS function is intended to retrieve or place a value into an object with the nested keys as a string.
For example
The method works, but I'd like to clean it up if possible (or a more polished implementation which is publicly available). I'd also love to know of any edge-case failures which can be found.
For example
var obj = {a: {b: [4]}};
parse_obj_key(obj, "a.b.0") should equal 4.
parse_obj_key(obj, "a.c", 2) should add another element to "a" named "c" with value 2.The method works, but I'd like to clean it up if possible (or a more polished implementation which is publicly available). I'd also love to know of any edge-case failures which can be found.
function parse_obj_key(obj, loc, val){
var _o = obj;
while (true){
var pos = loc.indexOf('.');
if (!_o || typeof _o != 'object'){
$.log("Invalid obj path: " + loc + "\n" + JSON.stringify(obj));
return null;
}
if (pos === -1){
if (val){
_o[loc] = val;
return obj;
} else {
if (!isNaN(parseInt(loc)))
loc = parseInt(loc);
return _o[loc];
}
}
var part = loc.substring(0, pos);
var loc = loc.substring(pos + 1);
if (!isNaN(parseInt(part)))
part = parseInt(part);
if (!(part in _o)){
if (val)
_o[part] = new object;
else
return null;
}
_o = _o[part];
}
}Solution
Here is what's wrong with your code:
-
Do not use variable names like
-
In general, doing those kinds of checks is a code smell.
-
JavaScript:
-
-
Consider using
So, here is a neat version for you:
Blogged: http://glebm.blogspot.com/2011/01/javascript-chained-nested-assignment.html
Please come up with further improvements :)
-
Do not use variable names like
_o. Get an editor with good auto-completion.-
typeof _o != 'object' does not do what you think it does: typeof([1,2]) // "object".In general, doing those kinds of checks is a code smell.
-
if (!isNaN(parseInt(loc))) loc = parseInt(loc);. Confusing and not needed.JavaScript:
['a', 'b']["1"] // 'b'. Same goes for the other isNaN-
in. Do not do that check. null is a value, but what you want to return is the lack of value. It is undefined in JavaScript, and it is what will be returned if there is no value.-
Consider using
split instead of indexOf and substring. It is much faster and makes the code more readable.So, here is a neat version for you:
function chained(obj, chain, value){
var assigning = (value !== undefined);
// split chain on array and property accessors
chain = chain.split(/[.\[\]]+/);
// remove trailing ']' from split
if (!chain[chain.length - 1]) chain.pop();
// traverse 1 level less when assigning
var n = chain.length - assigning;
for (var i = 0, data = obj; i < n; i++) {
data = data[chain[i]];
// if (data === undefined) return; // uncomment to handle bad chain keys
}
if (assigning) {
data[chain[n]] = value;
return obj;
} else {
return data;
}
}Blogged: http://glebm.blogspot.com/2011/01/javascript-chained-nested-assignment.html
Please come up with further improvements :)
Code Snippets
function chained(obj, chain, value){
var assigning = (value !== undefined);
// split chain on array and property accessors
chain = chain.split(/[.\[\]]+/);
// remove trailing ']' from split
if (!chain[chain.length - 1]) chain.pop();
// traverse 1 level less when assigning
var n = chain.length - assigning;
for (var i = 0, data = obj; i < n; i++) {
data = data[chain[i]];
// if (data === undefined) return; // uncomment to handle bad chain keys
}
if (assigning) {
data[chain[n]] = value;
return obj;
} else {
return data;
}
}Context
StackExchange Code Review Q#340, answer score: 3
Revisions (0)
No revisions yet.