fuzzybabybunny
fuzzybabybunny

Reputation: 5254

Using underscore _.extend to avoid overwriting nested objects?

var obj = {
  customerInfo: {
    fname: "Tom",
    lname: "Smith",
    age: 23,
    height: 160
  },
  car: {
    color: "red",
    numWheels: 4
  }
};

I would like to modify this object into:

var obj = {
  customerInfo: {
    fname: "Sally",
    lname: "Adams",
    mname: "Tully",
    age: 23,
    height: 160
  },
  car: {
    color: "red",
    numWheels: 4
  }
};

However, if I do

_.extend(obj, {
  customerInfo: {
    fname: "Sally", 
    lname: "Adams",
    mname: "Tully"
  }
});

the object becomes

{
  customerInfo: {
    fname: "Sally",
    lname: "Adams",
    mname: "Tully"
  },
  car: {
    color: "red",
    numWheels: 4
  }
};

and the age and height have been wiped out.

What do I need to do to preserve data that's nested?

And what about updating more complex objects?

http://jsfiddle.net/j4L18p7k/2/#share

Upvotes: 0

Views: 1156

Answers (2)

Filip
Filip

Reputation: 1244

There are better ways of achieving this deep merge behavior you're actually looking for...

You could use Jquery's $.extend API as documented here: http://api.jquery.com/jquery.extend/

I've put together this little example to match your code sample since I believe you that this kind of generic approach to merging is what you're actually looking for, right?

var o = {
  customerInfo: {
    fname: "Tom",
    lname: "Smith",
    age: 23,
    height: 160,
    paymentMethods: {
      paypal: {
        username: "sally"
      }
    }
  },
  car: {
    color: "red",
    numWheels: 4
  }
};

// this wipes out more deeply nested things (paypal disappears)
var merge = $.extend(true, {} , o.customerInfo, {
    "fname": "Sally",
    lname: "Adams",
    mname: "Tully",
    paymentMethods: {
      visa: {
        lastFour: "5555"
      }
    }
});

console.dir(merge);

http://jsfiddle.net/hrqbyd5c/9/

However pay attention to the JQuery docs

On a deep extend, Object and Array are extended, but object wrappers on primitive types such as String, Boolean, and Number are not. Deep-extending a cyclical data structure will result in an error.

For needs that fall outside of this behavior, write a custom extend method instead, or use a library like lodash.

Check out lodash's merge API documentation https://lodash.com/docs#merge

Hope this helped some more...

Upvotes: 1

Alex
Alex

Reputation: 8663

Extend customerInfo directly. Underscore .extend() replaces any key you mention, in this case removing any previous nested keys that aren't in your new object.

_.extend(obj.customerInfo, {
  fname: "Sally", 
  lname: "Adams",
  mname: "Tully"
});

Upvotes: 1

Related Questions