练习:js深拷贝

108 阅读1分钟

实现深拷贝

方法一:使用JSON

// 序列化 => 反序列化
const result = JSON.parse(JSON.stringify(data));

缺点:

  1. 不支持Date、正则、函数等
  2. 不支持引用

方法二:自己写

手写深拷贝的要点:

  1. 使用递归
  2. 判断类型
  3. 检查环
  4. 不拷贝原型上的属性
// 
const cache = new Map(); // Map的key可以是任意类型,Object的key是string
const deepClone = (data) => {

  // 对象
  if (data instanceof Object) {
    // 检查环
    if (cache.has(data)) {
      return cache.get(data);
    }

    let result;
    
    // data是函数
    if ( data instanceof Function ) {
      
      // 普通函数
      if ( data.prototype ) {
        result = function(){return data.apply(this, arguments);};
        
        // 箭头函数
      } else {
        result = (...args) => data.call(undefined, ...args);
      }
      
      // data是数组
    } else if (data instanceof Array) {
      result = [];
      
      // data是日期
    } else if (data instanceof Date) {
      result = new Date(data - 0);
      
      // data是正则
    } else if (data instanceof RegExp) {
      result = new RegExp(data.source, data.flags);
      
      // 其他默认为普通对象,有特殊情况,给上面加判断条件
    } else {
      result = {}; 
    }

    cache.set(data, result);
          
    for(let key in data) {
      // 不拷贝原型上的属性
      if (data.hasOwnProperty(key)) {
        result[key] = deepClone(data[key]);
      }
    } 
    
    return result;
    // 基本数据类型
  } else {
    return data;
  }
};

const x = {
  arr1: [1, 2, 3],
  arr2: [{a: 1}],
  fn1: function(a,b) {console.log('普通', a, b);},
  fn2: (a, b) => {console.log('箭头', a, b);},
  
};

function fn1(a, b) {
  console.log('普通函数a+b', a + b);
}


const fn2 = (a, b) => {
  console.log('箭头函数a-b:', a - b);
}