TotalAMD
TotalAMD

Reputation: 1016

Access to the nested object's fields

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

Answers (3)

brk
brk

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

Abhijit Kar ツ
Abhijit Kar ツ

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:

  1. Lodash is a must have tool-set in your JavaScript arsenal
  2. _.get() gets a property from deep within an object like so: _.get(obj, ["outer", "inner", "enable"])
  3. _.set() sets a property deep within an object

Checkout the respective documentations: GET & SET

Upvotes: 1

phuzi
phuzi

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

Related Questions