實(shí)現(xiàn)一個(gè)深拷貝函數(shù)(支持循環(huán)引用、Symbol、函數(shù)等特殊情況)

下面是一個(gè)完整的深拷貝實(shí)現(xiàn),考慮了循環(huán)引用、Symbol、函數(shù)、Date、RegExp、Map、Set等特殊類型:

function deepClone(target, map = new WeakMap()) {
  // 處理原始類型和函數(shù)(函數(shù)直接返回,因?yàn)橥ǔ2恍枰截悾?  if (typeof target !== 'object' || target === null) {
    return target;
  }

  // 處理循環(huán)引用
  if (map.has(target)) {
    return map.get(target);
  }

  // 處理Date對象
  if (target instanceof Date) {
    return new Date(target);
  }

  // 處理RegExp對象
  if (target instanceof RegExp) {
    return new RegExp(target);
  }

  // 處理Map
  if (target instanceof Map) {
    const clone = new Map();
    map.set(target, clone);
    target.forEach((value, key) => {
      clone.set(deepClone(key, map), deepClone(value, map));
    });
    return clone;
  }

  // 處理Set
  if (target instanceof Set) {
    const clone = new Set();
    map.set(target, clone);
    target.forEach(value => {
      clone.add(deepClone(value, map));
    });
    return clone;
  }

  // 處理Symbol
  if (typeof target === 'symbol') {
    return Symbol(target.description);
  }

  // 處理數(shù)組和普通對象
  const clone = Array.isArray(target) ? [] : {};
  map.set(target, clone);

  // 處理Symbol作為key的情況
  const symKeys = Object.getOwnPropertySymbols(target);
  if (symKeys.length) {
    symKeys.forEach(symKey => {
      clone[symKey] = deepClone(target[symKey], map);
    });
  }

  // 處理普通key
  for (const key in target) {
    if (target.hasOwnProperty(key)) {
      clone[key] = deepClone(target[key], map);
    }
  }

  return clone;
}

關(guān)鍵點(diǎn)解析

循環(huán)引用處理:

使用WeakMap來存儲已拷貝的對象,遇到相同的引用時(shí)直接返回存儲的副本

特殊對象處理:

Date:創(chuàng)建新的Date實(shí)例

RegExp:創(chuàng)建新的RegExp實(shí)例

Map/Set:遞歸拷貝其內(nèi)容

Symbol:創(chuàng)建新的Symbol,保持相同的description

函數(shù)處理:

函數(shù)直接返回原函數(shù),因?yàn)橥ǔ2恍枰截惡瘮?shù)

Symbol作為key:

使用Object.getOwnPropertySymbols()獲取Symbol key并遞歸拷貝

性能考慮:

使用WeakMap而不是Map,避免內(nèi)存泄漏

只在必要時(shí)創(chuàng)建新對象

使用示例

const obj = {
  num: 1,
  str: 'hello',
  arr: [1, 2, 3],
  date: new Date(),
  reg: /abc/gi,
  fn: function() { console.log('function') },
  [Symbol('sym')]: 'symbol value',
  map: new Map([['key', 'value']]),
  set: new Set([1, 2, 3])
};

// 創(chuàng)建循環(huán)引用
obj.self = obj;

const cloned = deepClone(obj);
console.log(cloned);
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容