返回

JS 深拷贝的巧妙实现

前端

深度拷贝是 JavaScript 中的常见操作,用于创建对象的完全副本,而不只是对其进行引用。但它的实现却往往令人头疼,因为需要考虑各种复杂情况,本文将通过基本类型、对象类型和特殊对象类型三种情况,手把手教你实现一个简单的深度拷贝函数,让你彻底掌握这个难题!

1. 基本类型直接返回

基本类型的值保存在栈内存中,值本身就是该类型的副本,因此对于基本类型(string、number、boolean、null、undefined),我们只需直接返回其值即可。

function deepCopy(obj) {
  if (typeof obj === 'string' || typeof obj === 'number' || typeof obj === 'boolean' || obj === null || obj === undefined) {
    return obj;
  }
}

2. 递归拷贝对象类型

对于对象类型的值,则需要进行递归拷贝。首先创建一个新的对象,然后遍历原对象的每个属性,对于每个属性,如果其值是基本类型,则直接复制;如果其值是对象类型,则递归调用 deepCopy 函数进行拷贝。

function deepCopy(obj) {
  if (typeof obj === 'object' && obj !== null) {
    const newObj = Array.isArray(obj) ? [] : {};
    for (const key in obj) {
      if (obj.hasOwnProperty(key)) {
        newObj[key] = deepCopy(obj[key]);
      }
    }
    return newObj;
  }
}

3. 处理特殊对象类型

对于特殊对象类型,如 Date、RegExp、Symbol 等,则需要特殊处理。我们可以使用相应的构造函数来创建新的对象,并将其值复制到新对象中。

function deepCopy(obj) {
  if (obj instanceof Date) {
    return new Date(obj);
  } else if (obj instanceof RegExp) {
    return new RegExp(obj);
  } else if (obj instanceof Symbol) {
    return Symbol(obj.toString());
  }
}

4. 完整实现

function deepCopy(obj) {
  if (typeof obj === 'string' || typeof obj === 'number' || typeof obj === 'boolean' || obj === null || obj === undefined) {
    return obj;
  } else if (typeof obj === 'object' && obj !== null) {
    const newObj = Array.isArray(obj) ? [] : {};
    for (const key in obj) {
      if (obj.hasOwnProperty(key)) {
        newObj[key] = deepCopy(obj[key]);
      }
    }
    return newObj;
  } else if (obj instanceof Date) {
    return new Date(obj);
  } else if (obj instanceof RegExp) {
    return new RegExp(obj);
  } else if (obj instanceof Symbol) {
    return Symbol(obj.toString());
  }
}

5. 总结

通过这篇文章,我们了解了基本类型、对象类型和特殊对象类型三种情况下的深度拷贝实现。希望大家在实际开发中灵活运用这些技巧,轻松应对各种数据拷贝的需求。