Last active
February 4, 2016 13:06
-
-
Save mmarinero/3c9d3247e615628c64d9 to your computer and use it in GitHub Desktop.
Two functions to traverse a chain of objects in Javascript. One to ask for a value at the end and one to place a value and create the intermediate objects if necessary. Both accept a variable length parameter's list or an array.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Tries to follow a chain of objects starting at base and return the value at | |
* the end. It uses a string array "mixedChain" to represent the chain and also | |
* accepts a variable number of string parameters representing the same chain so | |
* ask(object, ["child1", "child2"]) is equivalent to | |
* ask(object, "child1", "child2") | |
* If the chain keys are not strings convert them or use the array syntax | |
* | |
* @param {Object} base Root object of the chain to be inspected. | |
* @param {array[String] | ...String} mixedChain List of strings representing | |
* the objects properties chain. | |
* @return {mixed} value of the property at the end of the chain or undefined | |
* if not found. | |
*/ | |
var ask = function(base, mixedChain) { | |
var i = 0; | |
var chain = mixedChain; | |
if (Object.prototype.toString.call(chain) !== '[object Array]') { | |
chain = arguments; | |
i = 1; | |
} | |
while (i < chain.length - 1 && base !== undefined) { | |
base = base[chain[i]] || undefined; | |
i++; | |
} | |
return base ? base[chain[i]] : undefined; | |
}; | |
/** | |
* Builds a chain of objects if they don't exist and places a value at the end. | |
* It uses a string array "mixedChain" to represent the chain and also | |
* accepts a variable number of string parameters representing the same chain, or a | |
* single dot separated string that will be splitted and used as chain | |
* If the chain keys are not strings convert them or use the array syntax | |
* The last parameter is always the value to be placed. | |
* build(object, ["child1", "child2"], value) is equivalent to | |
* build(object, "child1", "child2", value) and equivalent to | |
* build(object, "child1.child2", value) | |
* | |
* @param {Object} base Root object of the chain to be used. | |
* @param {array[String] | ...String | String} mixedChain List of strings representing | |
* the objects properties chain. If it is a dot separated string, the string is splitted | |
* and used as if it were an array. (Use the array version if your second property names may have dots) | |
* @param {mixed} mixedVal Value to be placed at the end of the chain, it | |
* represents the last parameter although, positionally, it's the third. If it is an objects | |
* it will merge it's contents | |
*/ | |
var build = function(base, mixedChain, mixedVal) { | |
var args_index = 0; | |
var chain = mixedChain; | |
var val = mixedVal; | |
var isArray = Object.prototype.toString.call(chain) === '[object Array]'; | |
if (!isArray) { | |
var splitted = chain.split('.'); | |
if (splitted.length < 2) { | |
chain = arguments; | |
//if the chain is the arguments object avoid the base argument | |
args_index = 1; | |
} else { | |
chain = splitted; | |
} | |
val = arguments[arguments.length - 1]; | |
} | |
var i = args_index; | |
while (i < chain.length - args_index - 1) { | |
if (base[chain[i]] === undefined) { | |
base[chain[i]] = {}; | |
} | |
base = base[chain[i]]; | |
i++; | |
} | |
if (typeof val === 'object') { | |
base[chain[i]] = Object.assign(base[chain[i]] || {}, val); | |
} else { | |
base[chain[i]] = val; | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment