70

I am using an immutable object and want to clone or copy this object in order to make changes to it.

I have always been using the built-in Object.assign() and recently stumbled upon the jQuery's $.extend().

I was wondering, What is the better way to do this, and what exactly the difference is between both?

Looking at the documentation, I cannot seem to really find a notable difference concerning why to choose either one.

Timo Tijhof
  • 10,032
  • 6
  • 34
  • 48
Tikkes
  • 4,599
  • 4
  • 36
  • 62
  • 5
    Well.. for `$.extend` you need to have jQuery available. So the one difference is that one of them depend on an external library. If you already have jQuery in your project this point is kinda moot - but including an entire library just so that you can use one `$.extend` function doesn't seem like such a good idea. – Lix Jul 13 '16 at 08:08
  • I do have JQuery in my project, is there no difference between both then? Even when using arrays for example? – Tikkes Jul 13 '16 at 08:26
  • 2
    This post should be useful - http://stackoverflow.com/questions/122102/what-is-the-most-efficient-way-to-clone-an-object – Lix Jul 13 '16 at 08:30
  • I would accept if you post the first as an answer. otherwise I suppose this question can be closed. – Tikkes Jul 13 '16 at 09:06
  • no need to duplicate content :-) just upvote the answer that helped you most – Lix Jul 13 '16 at 09:07
  • Possible duplicate of [What is the most efficient way to deep clone an object in JavaScript?](http://stackoverflow.com/questions/122102/what-is-the-most-efficient-way-to-deep-clone-an-object-in-javascript) – Jacob van Lingen Mar 07 '17 at 12:30
  • It's often overlooked that many library features exist because the native functionality didn't at that point. – Álvaro González Apr 15 '17 at 13:50

1 Answers1

75

The two key differences are the optional boolean for deep merge which is recursive on the jQuery $.extend method (where false is not supported?!) ...

let object1 = {
  id: 1,
  name: {
    forename: 'John',
    surname: 'McClane'
  },
};

let object2 = {
  id: 2,
  name: {
  }
};

// merge objects
let objExtend = $.extend(true, {}, object1, object2);
let objAssign = Object.assign({}, object1, object2);

// diff
console.log(objExtend.name.forename); // "John"
console.log(objAssign.name.forename); //  undefined

Object.assign() copies property values. If the source value is a reference to an object, it only copies that reference value.

Example: JsFiddle

The second is the $.extend method ignores undefined ...

let object1 = {
  id: 1,
  name: 'hello world'
};

let object2 = {
  id: 2,
  name: undefined
};

// merge objects
let objExtend = $.extend({}, object1, object2);
let objAssign = Object.assign({}, object1, object2);

// diff
console.log(objExtend.name); // "hello world"
console.log(objAssign.name); //  undefined

Example: JsFiddle

Docs

MDN: Object.assign(target, ...sources)

jQuery: jQuery.extend([deep], target, object1 [, objectN])

Additionally:

If you are looking for a way to deep merge objects without jQuery, this answer is excellent:

How to deep merge instead of shallow merge?

Example: JsFiddle

How to deep merge using Object.assign with ES6:

function isObject(item) {
  return (item && typeof item === 'object' && !Array.isArray(item));
}

function mergeDeep(target, ...sources) {
  if (!sources.length) return target;
  const source = sources.shift();

  if (isObject(target) && isObject(source)) {
    for (const key in source) {
      if (isObject(source[key])) {
        if (!target[key]) Object.assign(target, { [key]: {} });
        mergeDeep(target[key], source[key]);
      } else {
        Object.assign(target, { [key]: source[key] });
      }
    }
  }
  return mergeDeep(target, ...sources);
}
Community
  • 1
  • 1
Matt D. Webb
  • 3,216
  • 4
  • 29
  • 51
  • 15
    Should mention another important difference - unlike `Object.assign`, jQuery ignores `undefined` fields in source objects. – riv Dec 13 '17 at 12:39
  • 1
    @riv thanks, I have now updated my answer to reflect this. – Matt D. Webb Feb 08 '18 at 00:20
  • 5
    *IMPORTANT* Hey guys, don't forget about the prototype. Prototype is not copied in Object.assign, but copied over in Jquery.extend – alcoforado Dec 04 '18 at 20:38