DeepClone

DeepClone

by Greg Finzer

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 }
  },
  pat: /w3schools/i
};

// 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(sourceObject) {
        var node;
        if (sourceObject === null || node['isActiveClone']) {
            node = sourceObject;
        }
        else if (typeof sourceObject === 'object' && Object.prototype.toString.call(sourceObject) === '[object Date]') {
            node = new Date(sourceObject.getTime());
        }
        else if (typeof sourceObject === 'object' && Object.prototype.toString.call(sourceObject) === '[object RegExp]') {
            node = new RegExp(sourceObject.source, getRegExpFlags(sourceObject));
        }
        else if (Array.isArray(sourceObject)) {
            node = sourceObject.slice(0) || [];
            for (var i = 0; i < node.length; i++) {
                var item = node[i];
                if (typeof item === 'object' && item !== {} || Array.isArray(item)) {
                    node[i] = deepClone(item);
                }
            }
        }
        else if (typeof sourceObject === 'object') {
            node = Object.assign({}, sourceObject);
            node['isActiveClone'] = true; // Handle circular references
            Object.keys(node).forEach(function (key) {
                if (typeof node[key] === 'object' && node[key] !== {}) {
                    node[key] = deepClone(node[key]);
                }
                delete node['isActiveClone'];
            });
        }
        else {
           ...