Reputation: 1016
I want to create function to toggle field value at any level of nested object
function toggle(object, field) {
object[field] = !object[field];
}
But if I want to change nested objects like this:
outer: {
inner: {
enable: true
}
}
I can't pass it just like toggle(outer, 'inner.price')
or toggle(outer.inner, 'price')
. Is there some trick with computed properties that allow me not to parse parameter string and dig inside object recursively?
Upvotes: 1
Views: 140
Reputation: 50291
Create a recursive function
var outer = {
inner: {
innerTwo: {
enable: true
}
}
}
function toggle(obj, keyName) {
for (var keys in obj) {
if (obj.hasOwnProperty(keys) && typeof obj[keys] === 'object') {
if (obj[keys][keyName] !== undefined) {
obj[keys][keyName] = !obj[keys][keyName]
} else {
toggle(obj[keys], keyName)
}
}
}
}
toggle(outer, 'enable');
console.log(outer)
Upvotes: 0
Reputation: 1732
Nothing beats Lodash in this regards
function toggle(obj, prop) {
_.set(obj, prop, !_.get(obj, prop));
}
var obj = {
outer: {
inner: {
enable: true
}
}
};
toggle(obj, ["outer", "inner", "enable"]);
console.log(obj);
toggle(obj, ["outer", "inner", "enable"]);
console.log(obj);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.min.js"></script>
Explanation:
Checkout the respective documentations: GET & SET
Upvotes: 1
Reputation: 13060
In JS you can actually get to properties by using their names and outer['inner']
is the same as outer.inner
but you don't need to know the property name at "compile" time.
You should be able to get away with splitting a string such as outer.inner.enable
to find the property you want with recursion.
let myObject = {
outer: {
inner: {
enable: true
}
}
};
const toggle = (object, path) => {
// get the name of the next property
let [prop, ...subProps] = path.split('.');
// check if the property to toggle is at this object
if (subProps.length == 0) {
// toggle said propertty
object[prop] = !object[prop];
} else {
// toggle property in child object
toggle(object[prop], subProps.join('.'));
}
}
console.log(myObject.outer.inner.enable); // true
toggle(myObject, 'outer.inner.enable');
console.log(myObject.outer.inner.enable); // false
Upvotes: 1