Found this excellent code for _.get vanilla js implementation:
const get = (obj, path, defaultValue) => path.split(".")
.reduce((a, c) => (a && a[c] ? a[c] : (defaultValue || null)), obj)
Now I'm looking for _.set implementation, any help would be appreciated.
I think this could cover it:
const set = (obj, path, value) => {
if (Object(obj) !== obj) return obj; // When obj is not an object
// If not yet an array, get the keys from the string-path
if (!Array.isArray(path)) path = path.toString().match(/[^.[\]]+/g) || [];
path.slice(0,-1).reduce((a, c, i) => // Iterate all of them except the last one
Object(a[c]) === a[c] // Does the key exist and is its value an object?
// Yes: then follow that path
? a[c]
// No: create the key. Is the next key a potential array-index?
: a[c] = Math.abs(path[i+1])>>0 === +path[i+1]
? [] // Yes: assign a new array object
: {}, // No: assign a new plain object
obj)[path[path.length-1]] = value; // Finally assign the value to the last key
return obj; // Return the top-level object to allow chaining
};
// Demo
var obj = { test: true };
set(obj, "test.1.it", "hello");
console.log(obj); // includes an intentional undefined value
It is a bit more complex than get, because there is some logic needed to create missing parts of the path in the object, to overwrite primitive values that stand in the way, and to determine whether a new child should better be an array or a plain object.
Check this one:
/**
* @example
* const obj = {id:1, address: {city: 'Minsk', street: 'Prityckogo 12'}}
* setByString(obj, 'address.city', 'Grodno'); obj.address.city => 'Grodno'
* setByString(obj, ['address', 'city'], 'Grodno'); obj.address.city => 'Grodno'
* setByString(obj, ['address', 'city', 'phones'], {mobile: 1234, home: 222}); obj.address.city.phones.home => 222
*/
/**
* @param {any} input
* @return {boolean}
*/
const isObject = (input) => (
null !== input &&
typeof input === 'object' &&
Object.getPrototypeOf(input).isPrototypeOf(Object)
)
**/
* @param {object} obj
* @param {string} path
* @param {any} value
*/
const setByString = (obj, path, value) => {
const pList = Array.isArray(path) ? path : path.split('.');
const len = pList.length;
// changes second last key to {}
for (let i = 0; i < len - 1; i++) {
const elem = pList[i];
if (!obj[elem] || !isObject(obj[elem])) {
obj[elem] = {};
}
obj = obj[elem];
}
// set value to second last key
obj[pList[len - 1]] = value;
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With