Edit in JSFiddle

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:',        object.d,     'cloned.d:',        cloned.d);
console.log(object.e === cloned.e,         'object.e:',        object.e,     'cloned.e:',        cloned.e);
console.log(object.f === cloned.f,         'object.f:',        object.f,     'cloned.f:',        cloned.f);
console.log(object.g === cloned.g,         'object.g:',     ...object.g,     'cloned.g:',     ...cloned.g);
console.log(object.h === cloned.h,         'object.h:',        object.h,     'cloned.h:',        cloned.h);
console.log(object.i.a === cloned.i.a,     'object.i.a:',      object.i.a,   'cloned.i.a:',      cloned.i.a);
console.log(object.i.b === cloned.i.b,     'object.i.b:',      object.i.b,   'cloned.i.b:',      cloned.i.b);
console.log(object.i.c === cloned.i.c,     'object.i.c:',      object.i.c,   'cloned.i.c:',      cloned.i.c);
console.log(object.i.d === cloned.i.d,     'object.i.d:',      object.i.d,   'cloned.i.d:',      cloned.i.d);
console.log(object.i.e === cloned.i.e,     'object.i.e:',      object.i.e,   'cloned.i.e:',      cloned.i.e);
console.log(object.i.f === cloned.i.f,     'object.i.f:',      object.i.f,   'cloned.i.f:',      cloned.i.f);
console.log(object.i.g === cloned.i.g,     'object.i.g:',   ...object.i.g,   'cloned.i.g:',   ...cloned.i.g);
console.log(object.i.h === cloned.i.h,     'object.i.h:',      object.i.h,   'cloned.i.h:',      cloned.i.h);
console.log(object.i.i.a === cloned.i.i.a, 'object.i.i.a:',    object.i.i.a, 'cloned.i.i.a:',    cloned.i.i.a);