js/object-helpers.js
/**
* Safely access deeply nested values in an object. If the path to the value is not valid,
* the method will gracefully return null.
*
* @param {array} path - the array representation of the path to access.
* @param {object} obj - the object who's value you are trying to access.
*
* @return {null | any} will return null on path not found, or the value found.
*/
exports.accessDeep = function (path, obj) {
if (typeof path === "string") {
path = path.split(".");
}
return path.reduce(function (xs, x) { return (xs && xs[x]) ? xs[x] : null;}, obj);
};
/**
* The mapObj() method creates a new array with the results of calling a provided function
* on every element in the calling object.
*
* @param {object} obj - The object to map.
* @param {function} callback - The function to call per iterated value.
* @returns {array} returns an array with the values of each returned value in the callback.
*/
exports.mapObj = function (obj, callback) {
return Object.keys(obj).map(function (key) {
const returning = callback(obj[key], key);
if(returning !== false){
return returning;
}
});
};
/**
* Callback for mapObj
*
* The result of this will be added to the array.
*
* @callback mapObj
* @param {any} arg[1] - The value of the current object value being iterated through.
* @param {string} arg[2] - The key of the current object value being iterated through.
*/
/**
* Deeply nest and set a value in an object.
*
* @param {object} obj - The target object
* @param {array | string } path - The path where the value should be nested and set.
* @param {any} value - The value to set
* @param {boolean} setRecursively - Should create path if the path does not exist.
* @returns {object} Returns the new object for reference purposes.
*/
exports.setDeep = function (obj, path, value, setRecursively = false) {
let level = 0;
if (typeof path === "string") {
path = path.split(".");
}
level = 0;
path.reduce((a, b)=>{
level++;
if (setRecursively && typeof a[b] === "undefined" && level !== path.length){
a[b] = {};
return a[b];
}
if (level === path.length){
a[b] = value;
return value;
} else {
return a[b];
}
}, obj);
return obj;
};
/**
* Quickly call a function or fail gracefully if it does not exist.
*
* @param {function} func - The function to try to call.
* @param {args} args - The would-be arguments of the function.
* @returns {any} returns whatever the function returns.
*/
exports.ifFunc = function (func, ...args){
if (typeof func === "function") {
return func(...args);
}
};
/**
* Group an array's values into subgroups.
*
* @param {array} arr - The target array.
* @param {number} len - The length of the chunks.
* @returns {array} A two-dimensional segmented array.
*/
exports.arrayChunks = function (arr, len){
let chunks = [],
i = 0,
n = arr.length;
while (i < n) {
chunks.push(arr.slice(i, i += len));
}
return chunks;
};