返回

浅析“深浅拷贝”的精髓,避开JS编程中的常见坑

前端

深入浅出话拷贝

JavaScript 中的数据类型大致分为基本数据类型和引用数据类型。基本数据类型保存在栈数据结构中,按值访问,不存在深浅拷贝问题。引用数据类型保存在堆数据结构中,按引用访问,深浅拷贝就显得尤为重要。

深拷贝是完整复制数据的值(而非引用), 目的是避免拷贝后数据对原数据产生影响。与之相对的浅拷贝只复制引用,源数据和拷贝数据共享内存地址,导致修改其中任何一个,另一个也会受到影响。

浅尝辄止看浅拷贝

接下来,我们来揭秘浅拷贝的常用方法。

方法一:Object.assign()

let obj1 = { name: 'Tom', age: 20 };
let obj2 = Object.assign({}, obj1); // 浅拷贝

方法二:扩展运算符(...)

let obj1 = { name: 'Tom', age: 20 };
let obj2 = {...obj1}; // 浅拷贝

使用上述方法进行浅拷贝时,对象中的基本数据类型会被复制一份新的值,而引用数据类型则会指向同一个内存地址。因此,当修改浅拷贝对象中的引用数据类型时,原始对象中的数据也会受到影响。

拷贝利器说深拷贝

深拷贝实现相对复杂一些, 但其本质就是递归的克隆源对象, 直到对象中的所有引用数据类型都完成复制。常用的深拷贝方法有:

方法一:JSON.parse(JSON.stringify())

let obj1 = { name: 'Tom', age: 20 };
let obj2 = JSON.parse(JSON.stringify(obj1)); // 深拷贝

方法二:递归函数

function deepCopy(obj) {
  if (typeof obj !== 'object' || obj === null) {
    return obj; // 基本数据类型或null直接返回
  }

  let newObj = Array.isArray(obj) ? [] : {};
  for (let key in obj) {
    newObj[key] = deepCopy(obj[key]); // 递归复制属性值
  }

  return newObj;
}

let obj1 = { name: 'Tom', age: 20 };
let obj2 = deepCopy(obj1); // 深拷贝

使用上述方法进行深拷贝时,无论对象中的数据类型是基本数据类型还是引用数据类型,都会被复制一份新的值,从而避免了浅拷贝中引用数据类型指向同一个内存地址的问题。

结语

深浅拷贝是JS编程中常见的基础知识。理解深浅拷贝的原理和区别,并熟练掌握常用的深浅拷贝方法,是编写高质量JS代码的基础。希望本文对您有所帮助。