返回

剖析JS数据类型:深拷贝与浅拷贝的玄妙之处

前端

在JavaScript中,变量可以保存不同类型的数据,即数据类型,它们决定了数据的存储方式和操作方式。基本数据类型包括undefined、null、boolean、number、string和symbol,而引用数据类型主要有object、array和function。理解数据类型对于理解浅拷贝与深拷贝的区别至关重要。

深拷贝与浅拷贝的概念

当我们把一个变量的值赋给另一个变量时,实际上只是复制了变量的引用,而不是复制变量的值,如果变量保存的是基本数据类型的值,则会进行值拷贝;如果变量保存的是引用数据类型的值,则会进行引用拷贝。

1. 浅拷贝

浅拷贝只复制变量保存的引用数据类型的值,而不复制引用数据类型的值本身。例如,我们有一个对象obj1,它包含一个数组arr。当我们使用浅拷贝的方式将obj1复制到obj2时,obj2也将引用arr,而不是复制一个新的数组。因此,如果我们修改arr,obj1和obj2都将受到影响。

2. 深拷贝

深拷贝不仅复制变量保存的引用数据类型的值,还复制引用数据类型的值本身。例如,我们有一个对象obj1,它包含一个数组arr。当我们使用深拷贝的方式将obj1复制到obj2时,obj2将创建一个新的数组,并复制arr中的所有元素。因此,如果我们修改arr,obj1和obj2将不受影响。

深拷贝与浅拷贝的区别

  • 浅拷贝只复制变量保存的引用数据类型的值,而深拷贝不仅复制变量保存的引用数据类型的值,还复制引用数据类型的值本身。
  • 浅拷贝只会创建一个新变量,并使其引用与原变量相同的对象,而深拷贝会创建一个新的对象,并将原对象的属性复制到新对象。
  • 浅拷贝不会影响原对象,而深拷贝可能会影响原对象。

如何进行深拷贝和浅拷贝

1. 如何进行浅拷贝

  • 使用赋值运算符(=)进行浅拷贝,例如:
let obj1 = {name: 'John', age: 20};
let obj2 = obj1;
  • 使用Object.assign()方法进行浅拷贝,例如:
let obj1 = {name: 'John', age: 20};
let obj2 = Object.assign({}, obj1);

2. 如何进行深拷贝

  • 使用JSON.parse(JSON.stringify(obj))方法进行深拷贝,例如:
let obj1 = {name: 'John', age: 20};
let obj2 = JSON.parse(JSON.stringify(obj1));
  • 使用lodash.cloneDeep()方法进行深拷贝,例如:
let obj1 = {name: 'John', age: 20};
let obj2 = _.cloneDeep(obj1);
  • 使用递归函数进行深拷贝,例如:
function deepCopy(obj) {
  if (typeof obj !== 'object' || obj === null) {
    return obj;
  }

  if (Array.isArray(obj)) {
    return obj.map(item => deepCopy(item));
  }

  const newObj = {};
  for (let key in obj) {
    newObj[key] = deepCopy(obj[key]);
  }

  return newObj;
}

总结

浅拷贝和深拷贝是JavaScript中常用的两种拷贝方法,它们的区别在于浅拷贝只复制变量保存的引用数据类型的值,而深拷贝不仅复制变量保存的引用数据类型的值,还复制引用数据类型的值本身。我们可以使用赋值运算符、Object.assign()方法、JSON.parse(JSON.stringify(obj))方法、lodash.cloneDeep()方法或递归函数来进行浅拷贝或深拷贝。

掌握浅拷贝和深拷贝的概念和实现方法,可以帮助我们更好地理解和操作JavaScript中的数据,避免在编写代码时出现问题。