Deep copy in ES6 without library

by bc_rikko

JavaScript

const object = {
  // プリミティブ型
  a: 1,
  b: 'a',
  c: '',
  d: null,
  e: undefined,
  f: true,
  // 参照型
  g: [1, 2, 3],
  h: function () { console.log('h'); },
  i: {
    a: 1,
    b: 'a',
    c: '',
    d: null,
    e: undefined,
    f: true,
    g: [1, 2, 3],
    h: function () { console.log('h'); },
    i: { a: 1 }
  }
};

// lodash
// const obj = _.cloneDeep(object);

// jQuery
// const obj = $.extend({}, object);

// Deep copy? (undefinedやfunctionが消えてしまう)
// const obj = JSON.parse(JSON.stringify(object));

// 勘違い(ES6) → シャローコピー
// const obj = Object.assign({}, object);

function deepClone(object) {
  let node;
  if (object === null) {
    node = object;
  }
  else if (Array.isArray(object)) {
    node = object.slice(0) || [];
    node.forEach(n => {
      if (typeof n === 'object' && n !== {} || Array.isArray(n)) {
        n = deepClone(n);
      }
    });
  }
  else if (typeof object === 'object') {
    node = Object.assign({}, object);
    Object.keys(node).forEach(key => {
      if (typeof node[key] === 'object' && node[key] !== {}) {
        node[key] = deepClone(node[key]);
      }
    });
  }
  else {
    node = object;
  }
  return node;
}

const cloned = deepClone(object);

// Modify
object.a = 2;
object.b = 'b';
object.c = '_';
object.d = 'null';
object.e = 'undefined';
object.f = false;
object.g = [3, 2, 1];
object.h = function () { console.log('cloned'); }
object.i.a = 2;
object.i.b = 'b';
object.i.c = '_';
object.i.d = 'null';
object.i.e = 'undefined';
object.i.f = false;
object.i.g = [3, 2, 1];
object.i.h = function () { console.log('cloned'); }
object.i.i.a = 2;

// Check
console.log(object.a === cloned.a,         'object.a:',        object.a,     'cloned.a:',        cloned.a);
console.log(object.b === cloned.b,         'object.b:',        object.b,     'cloned.b:',        cloned.b);
console.log(object.c === cloned.c,         'object.c:',        object.c,     'cloned.c:',        cloned.c);
console.log(object.d === cloned.d,         'object.d:',...