2

I'm trying to write a function that will let me update my kitchen in this example below. Using something like underscore's extend, however, blows away the beer in my fridge as it's updating the entire fridge object.

Is there a simple method I can use so that I only make updates with the properties that change in my changeKitchen object and not update the entire fridge object?

// My original kitchen
var kitchen = {
  fridge: {
    beer: true,
    celery: false
  },
  cabinets: {
    candy: true
  }
};


// updates I would like to make to my kitchen
var changeKitchen = {
  fridge: {
    celery: true
  }
};


var updatedKitchen = _.extend(kitchen, changeKitchen);

console.log(updatedKitchen);

Returns

var kitchen = {
  fridge: {
    celery: false // beer is gone
  },
  cabinets: {
    candy: true
  }
};

However I would like to have:

var kitchen = {
  fridge: {
    beer: true,
    celery: true // changed
  },
  cabinets: {
    candy: true
  }
};
Ben
  • 5,283
  • 9
  • 35
  • 44

4 Answers4

4

Since you're already using Underscore, you could use Lodash instead, which is a superset of Underscore, and use its #merge function.

See this question about Differences between Lodash and underscore

// My original kitchen
var kitchen = {
  fridge: {
    beer: true,
    celery: false
  },
  cabinets: {
    candy: true
  }
};


// updates I would like to make to my kitchen
var changeKitchen = {
  fridge: {
    celery: true
  }
};


var updatedKitchen = _.merge(kitchen, changeKitchen);

document.write(JSON.stringify(updatedKitchen));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.js"></script>
Community
  • 1
  • 1
Merott
  • 7,189
  • 6
  • 40
  • 52
2

Use _.extend on the nested objects instead:

function update(obj1, obj2) {
  for (var p in obj2) {
    if (obj1[p]) {
        _.extend(obj1[p], obj2[p]);
    } else {
      obj1[p] = obj2[p];
    }
  }
}

update(kitchen, changeKitchen);

DEMO

Andy
  • 61,948
  • 13
  • 68
  • 95
1

Here is a solution in plain Javascript:

var kitchen = { fridge: { beer: true, celery: false }, cabinets: { candy: true } },
    changeKitchen = { fridge: { celery: true } };

function update(source, target) {
    Object.keys(target).forEach(function (k) {
        if (typeof target[k] === 'object') {
            source[k] = source[k] || {};
            update(source[k], target[k]);
        } else {
            source[k] = target[k];
        }
    });
}

update(kitchen, changeKitchen);
document.write('<pre>' + JSON.stringify(kitchen, 0, 4) + '</pre>');
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
0

Try using for..in loop , Object.keys()

// My original kitchen
var kitchen = {
  fridge: {
    beer: true,
    celery: false
  },
  cabinets: {
    candy: true
  }
};

var changeKitchen = {
  fridge: {
    celery: true
  }
};

for (var prop in changeKitchen) {
  if (kitchen[prop]) {
    kitchen[prop]
      [Object.keys(changeKitchen[prop])] = changeKitchen[prop]
         [Object.keys(changeKitchen[prop])]
  }
}

console.log(kitchen)
guest271314
  • 1
  • 15
  • 104
  • 177