Shallow,Deep Copy,Comparison

Copying

The '=' sign merely copies the reference (memory address) of the object.


var a = ['a', 'b', 'c'];
var b = a;
b.push('d'); // item added to ‘a’ too!
console.log(a);

var c = a.slice();
c.push('e'); // item not added to ‘a’
console.log(a);

["a", "b", "c", "d"] ["a", "b", "c", "d"]

To create a clone, use:

Object.assign({}, obj)to perform ashallow copy. If you wish to copy an array, you can use arr.slice() instead.

JSON.parse(JSON.stringify(obj )) if the values include literal structures such as [] and {} but not those in 3.

jQuery $.extend(obj) if the values include prototypes such as:

new Bool(true)

new Array() new Object() function(){}

The following shows an attempt to implement a deep copy function, which uses recursion. It has some limitations: no cyclic structures allowed, Symbols not copied etc.


function clone(obj) {
  var copy;
  if (null == obj || "object" != typeof obj) return obj;

  if (obj instanceof Date) {
    copy = new Date();
    copy.setTime(obj.getTime());
    return copy;
  }

  if (obj instanceof Array) {
    copy = [];
    for (let i = 0, len = obj.length; i < len; i++) copy[i] = clone(obj[i]);
    return copy;
  }

  if (obj instanceof Object) {
    copy = {};
    for (let attr in obj) {
      if (obj.hasOwnProperty(attr)) copy[attr] = clone(obj[attr]);
    }
    return copy;
  }

  throw new Error("Unable to clone object! ");
}

ComparingUnless the operands point to the same reference, '==' and '===' never return true for objects comparison.

JSON.stringify(o1) === JSON.stringify(o2)The above attempt will fail when the orders of the properties are different.Some libraries such as Lodash, AngularJS, Ember etc. provide an object comparison function. If you have a deep copy function ready, you can perform a 'deep comparison' for objects using the following technique:


function equals(o1, o2) {
  function _equals(a, b) {
    return JSON.stringify(a) === JSON.stringify($.extend(true, {}, a, b));
  }
  return _equals(o1, o2) && _equals(o2, o1);
}