返回

使用JS实现深拷贝而不丢失数据类型

前端

浅拷贝与深拷贝:
浅拷贝是指仅复制对象的引用,而深拷贝是指复制对象的全部内容,包括其属性和嵌套对象。

const obj1 = {
  name: 'John',
  age: 30,
  hobbies: ['music', 'sports'],
};

const obj2 = obj1; // 浅拷贝

obj2.name = 'Jane'; // 更改 obj2.name 会影响 obj1.name
console.log(obj1.name); // 输出: 'Jane'

可以看到,当我们对obj2.name进行更改时,obj1.name也随之改变。这是因为obj2只是一个指向obj1的引用,所以更改obj2实际上就是更改了obj1。

为了避免这种情况,我们需要进行深拷贝。我们可以使用递归来实现深拷贝:

const deepCopy = (obj) => {
  if (typeof obj !== 'object' || obj === null) {
    return obj; // 如果不是对象或为null,直接返回
  }

  if (Array.isArray(obj)) {
    return obj.map((item) => deepCopy(item)); // 如果是数组,递归复制每个元素
  }

  const newObj = {};
  for (const key in obj) {
    newObj[key] = deepCopy(obj[key]); // 如果是对象,递归复制每个属性
  }

  return newObj;
};

现在,我们可以使用deepCopy函数来进行深拷贝:

const obj1 = {
  name: 'John',
  age: 30,
  hobbies: ['music', 'sports'],
};

const obj2 = deepCopy(obj1); // 深拷贝

obj2.name = 'Jane'; // 更改 obj2.name 不会影响 obj1.name
console.log(obj1.name); // 输出: 'John'

可以看到,当我们对obj2.name进行更改时,obj1.name保持不变。这是因为深拷贝创建了一个新的对象,其中包含了obj1的所有属性和嵌套对象。

丢失数据类型的问题:

在实现深拷贝时,我们可能会遇到一些问题,比如丢失数据类型。

例如,如果我们有一个包含日期类型属性的对象,在进行深拷贝时,日期类型属性可能会变成字符串类型。这是因为JSON.stringify()函数会将日期类型转换为字符串类型。

为了解决这个问题,我们需要在deepCopy函数中对日期类型属性进行特殊处理。我们可以使用Date.parse()函数来将字符串类型的日期转换为日期类型。

const deepCopy = (obj) => {
  if (typeof obj !== 'object' || obj === null) {
    return obj; // 如果不是对象或为null,直接返回
  }

  if (Array.isArray(obj)) {
    return obj.map((item) => deepCopy(item)); // 如果是数组,递归复制每个元素
  }

  const newObj = {};
  for (const key in obj) {
    if (obj[key] instanceof Date) {
      newObj[key] = new Date(obj[key]); // 如果是日期类型,使用Date.parse()函数进行转换
    } else {
      newObj[key] = deepCopy(obj[key]); // 如果是其他类型,递归复制每个属性
    }
  }

  return newObj;
};

现在,我们就可以对包含日期类型属性的对象进行深拷贝,而不丢失数据类型。

正则表达式的数据类型:

正则表达式也是一种特殊的数据类型。在进行深拷贝时,我们需要对正则表达式属性进行特殊处理。

我们可以使用正则表达式的构造函数RegExp()来创建新的正则表达式对象。

const deepCopy = (obj) => {
  if (typeof obj !== 'object' || obj === null) {
    return obj; // 如果不是对象或为null,直接返回
  }

  if (Array.isArray(obj)) {
    return obj.map((item) => deepCopy(item)); // 如果是数组,递归复制每个元素
  }

  const newObj = {};
  for (const key in obj) {
    if (obj[key] instanceof Date) {
      newObj[key] = new Date(obj[key]); // 如果是日期类型,使用Date.parse()函数进行转换
    } else if (obj[key] instanceof RegExp) {
      newObj[key] = new RegExp(obj[key].source, obj[key].flags); // 如果是正则表达式,使用RegExp()函数进行转换
    } else {
      newObj[key] = deepCopy(obj[key]); // 如果是其他类型,递归复制每个属性
    }
  }

  return newObj;
};

现在,我们就可以对包含正则表达式属性的对象进行深拷贝,而不丢失数据类型。

通过使用递归和对特殊数据类型进行特殊处理,我们可以实现深拷贝,而不丢失数据类型。