JavaScript 深拷贝

JSON

const copy = JSON.parse(JSON.stringify(a));

缺点

  1. 不支持 Date、正则、undefined、函数等数据
  2. 不支持引用,即环状结构

递归

要点:

  1. 判断类型 => instanceof
  2. 检查环 => 使用哈希表缓存
  3. 不拷贝原型上的属性 => hasOwnPropertype
const deepCopy = (a, cache) => {
  if (!cache) {
    cache = new Map();
  }

  // 不考虑跨 iframe
  if (a instanceof Object) {
    if (cache.get(a)) {
      return cache.get(a);
    }
    let result = null;
    if (a instanceof Function) {
      // 有 prototype 就是普通函数
      if (a.prototype) {
        result = function () {
          return a.apply(this, arguments);
        }
      } else {
        result = (...args) => {
          return a.call(undefined, ...args);
        }
      }
    } else if (a instanceof Array) {
      result = [];
    } else if (a instanceof Date) {
      result = new Date(a - 0);
    } else if (a instanceof RegExp) {
      result = new RegExp(a.source, a.flags);
    } else {
      result = {};
    }
    cache.set(a, result);
    for (let key in a) {
      if (a.hasOwnProperty(key)) {
        result[key] = deepCopy(a[key], cache);
      }
    }
    return result;
  }
  return a;
}

const a = {
  number: 1, bool: false, str: 'hi', empty1: undefined, empty2: null,
  array: [
    {name: 'frank', age: 18},
    {name: 'jacky', age: 19}
  ],
  date: new Date(2000, 0, 1, 20, 30, 0),
  regex: /\.(j|t)sx/i,
  obj: {name: 'frank', age: 18},
  f1: (a, b) => a + b,
  f2: function (a, b) { return a + b }
}
a.self = a;

const b = deepCopy(a);
console.log(b.self === b); // true
b.self = 'hi'
console.log(a.self !== 'hi'); //true

你可能感兴趣的:(JavaScript 深拷贝)