Question

This works fine:

.extend(true, {}, { name: "john doe", age: 20, address: {street:"aaa", number:"bbb"} }, { gender: "M", address: {} })

But when address is a class then the second address overrides the first one instead of merging them.

function Address(data) {
    this.data = data;
}

$.extend(true, {}, { name: "john doe", age: 20, address: new Address({street:"aaa", number:"bbb"}) }, { gender: "M", address: new Address({}) })

Is that a bug or an expected behavior of jQuery? How do I merge two instances of a class?

Was it helpful?

Solution

To add to the other answer, you could try to convert it to a plain object, although I'm not sure if this is the right approach, but it should work:

function Person(name) {
  this.name = name;
}

Person.prototype.say = function() {
  return this.name + ' says hello!';
};

var toPlainObject = function(x) {
  var obj = Object.create(null);
  for (var i in x) obj[i] = x[i];
  return obj;
};

// false
// Person {name: 'John', say: function}
$.isPlainObject(new Person('John'));
// true
// Object {name: 'John', say: function}
$.isPlainObject(toPlainObject(new Person('John')));

OTHER TIPS

jQuery.extend always copies from right to left. The second overrides the first, and the third overrides the second. Therefore, the property value of address from the third of course overrides the property value of the second. It doesn't merge deeper than that because the property value of address fails the jQuery.isPlainObject() test.

function Address(data) {
    this.data = data;
}

console.log( jQuery.isPlainObject(new Address()) ); // false

if Address instead returned a plain object, this wouldn't happen.

function Address(data) {
    var obj = {};
    obj.data = data;
    return obj;
}

console.log( jQuery.isPlainObject(Address()) ); // false
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top