Inchara Raveendra
Inchara Raveendra

Reputation: 1667

Find a key in nested object and replace its value - Javascript

Here is my fiddle : DEMO

By recursive iterations, I am able to find the key in object2 object3 and replace its value by the values from data2 data3 objects.

However, I am unable to replace the value if it is an array. (key called 'coordinates' in this case) How could this be fixed?

function update(object, data) {
  function getAllKeys(o) {
    Object.keys(o).forEach(function(k) {
      if (typeof o[k] === 'object') {
        return getAllKeys(o[k]);
      }
      keys[k] = o;
    });
  }
  var keys = Object.create(null);
  getAllKeys(object);
  Object.keys(data).forEach(function(k) {
    if (keys[k] && k in keys[k]) { // check if key for update exist
      keys[k][k] = data[k];
    }
  });
}

Upvotes: 1

Views: 2992

Answers (3)

kiddorails
kiddorails

Reputation: 13014

Update the getAllKeys method with:

  function getAllKeys(o) {
    Object.keys(o).forEach(function(k) {
      contains_object = Array.isArray(o[k]) && o[k].some(val=> { return typeof val == "object" && !Array.isArray(val);  });
      if ((Array.isArray(o[k]) && !contains_object)  || typeof o[k] !== 'object') {
        keys[k] = o;
      } else {
        return getAllKeys(o[k]);
      }
      keys[k] = o;
    });
  }

Note: !(o[k] instanceof Array) - http://jsfiddle.net/08pnu7rx/1/

Upvotes: 2

Shubham Khatri
Shubham Khatri

Reputation: 281626

The problem in your code is that typeof o[k] === 'object' returns true even it o[k] is an array which is the case for coordinated, You need a negative check for array too like

Object.keys(o).forEach(function(k) {
  if (typeof o[k] === 'object'&& !Array.isArray(o[k])) {
    return getAllKeys(o[k]);
  }
  keys[k] = o;
});

Working fiddle

According to the docs or typeof:

// use Array.isArray or Object.prototype.toString.call
// to differentiate regular objects from arrays
typeof [1, 2, 4] === 'object';

Upvotes: 0

Cobus Kruger
Cobus Kruger

Reputation: 8605

The problem is that typeof also returns object for arrays.

You want to change your function to still assign the key when the object is an array.

function getAllKeys(o) {
  Object.keys(o).forEach(function(k) {
    if (Array.isArray(o[k]) || typeof o[k] !== 'object') {
      keys[k] = o;
    } else {
      return getAllKeys(o[k]);
    }
  });
}

Notice I swapped around the logic, so you first check for either an array or another non-object type. If that check passes, you assign the value. If not, you recurse.

You should note that this is not at all specific to arrays. You will have similar problems if you have a nested property that is a Date, for example.

Upvotes: 0

Related Questions