Skip to content

Instantly share code, notes, and snippets.

@vsambor
Last active June 4, 2019 08:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vsambor/3df9ad75ff3de489bbcb7b8c60beebf4 to your computer and use it in GitHub Desktop.
Save vsambor/3df9ad75ff3de489bbcb7b8c60beebf4 to your computer and use it in GitHub Desktop.
A JavaScript function which assures that a value of a child chain property is returned without runtime errors.
const obj = {
c: {
a: 2,
b: {
c: [1, 2, 3, {a: 15, b: 10}, 15]
},
c: undefined,
d: null
},
d: ''
}
/**
* Assures that a value of a child chain property is returned without runtime errors.
*
* If the checked property does not exist in the provided object or one of the children in the chain
* is undefined, then it returns the provided fallback value.
*
* The fallback can be also returned if the checked property is falsy (i.e. undefined, null, false, 0, '', etc.)
* and the fallbackOnFalsy flag is set to <TRUE>.
*
* Arrays could be checked as well by passing the index in the path; ex: getValue(arr, '0.obj')
*
* Note: if object or path params are not provided, the fallback is returned.
*
* @param {Object|Array} object - ordinary JSON object or array in which the property value is checked.
* @param {String | Array} path - object property access chain; ex: 'a.b.c' or ['a', 'b.c', 'd'].
* @param {*} fallback - the fallback value.
* @param {Boolean} fallbackOnFalsy - if true and the found property value is falsy then it returns the fallback.
*
* @returns {*} - the deepest property value or the fallback.
*/
getValue(object, path, fallback, fallbackOnFalsy) {
if (!object || !path) {
return fallback;
}
if (typeof path === 'string') {
path = path.split('.');
}
// Reduces object properties to the deepest property in the path argument.
return path.reduce((object, property) => {
if (object && typeof object !== 'string' && object.hasOwnProperty(property)) {
// The property is found but it may be falsy.
// If fallback is active for falsy values, the fallback is returned, otherwise the property value.
return !object[property] && fallbackOnFalsy ? fallback : object[property];
} else {
// Returns the fallback if current chain link does not exist or it does not contain the property.
return fallback;
}
}, object);
}
// Same as get value but slightly unreadable.
// function getValue(o, path, fb, fbFalsy) {
// if(!o || !path) return fb;
// return path.split('.').reduce((o, p) => o && typeof o !== 'string' && o.hasOwnProperty(p) ? !o[p] && fbFalsy ? fb : o[p] : fb, o);
// }
// Shorter version. which does not apply fallback for falsy values, it just returnes what it finds.
// function getValue(o, path, fb) {
// if(!o || !path) return fb;
// return path.split('.').reduce((o, p) => o && typeof o !== 'string' && o.hasOwnProperty(p) ? o[p] : fb, o);
// }
// fallback
console.log(getValue(null, 'c.d.d', 'fallback'))
// fallback
console.log(getValue(obj, null, 'fallback'))
// fallback
console.log(getValue(null, null, 'fallback'))
// fallback
console.log(getValue(obj, 'c.d.d', 'fallback'))
// null
console.log(getValue(obj, 'c.d', 'fallback'));
// array
console.log(getValue(obj, 'c.b.c', 'fallback'));
// array index 2
console.log(getValue(obj, 'c.b.c.2', 'fallback'));
// no index => fallback
console.log(getValue(obj, 'c.b.c.10', 'fallback'));
// array no index, no fallback => undefined
console.log(getValue(obj, 'c.b.c.10'));
// array's object property
console.log(getValue(obj, 'c.b.c.3.a'));
// array property length
console.log(getValue(obj, 'c.b.c.length', 'fallback'));
// prints falsy object
console.log(getValue(obj, 'c.c', 'fallback'));
// prints fallback for falsy values
console.log(getValue(obj, 'c.c', 'fallback', true));
// prints fallback
console.log(getValue(obj, 'c.z.1', 'fallback'));
// prints fallback
console.log(getValue(obj, 'c.z.1', 'fallback', true));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment