JS 中的深拷贝与浅拷贝

什么是深拷贝与浅拷贝

在 JavaScript 中,深拷贝和浅拷贝是两种不同的对象复制方式。浅拷贝只复制对象的引用,而深拷贝则会复制整个对象,包括对象的所有属性和嵌套对象。

深拷贝的实现

JSON.parse(JSON.stringify())

用于将一个对象转换为 JSON 字符串,然后再将 JSON 字符串转换回对象。该方法可以实现深拷贝,因为它会复制整个对象,包括对象的所有属性和嵌套对象。例如:

const obj1 = { a: 1, b: { c: 2 } } const obj2 = JSON.parse(JSON.stringify(obj1)) console.log(obj2) // { a: 1, b: { c: 2 } } console.log(obj1 === obj2) // false

但是,该方法也有一些缺点:

  • 会忽略 undefined
  • 会忽略 symbol
  • 不能序列化函数
  • 不能解决循环引用的对象

递归复制

递归复制是一种手动实现深拷贝的方法。该方法通过递归遍历对象的所有属性和嵌套对象,并将它们复制到一个新对象中。例如:

function deepCopy(obj) { if (typeof obj !== 'object' || obj === null) { return obj } const newObj = Array.isArray(obj) ? [] : {} for (const key in obj) { newObj[key] = deepCopy(obj[key]) } return newObj } const obj1 = { a: 1, b: { c: 2 } } const obj2 = deepCopy(obj1) console.log(obj2) // { a: 1, b: { c: 2 } } console.log(obj1 === obj2) // false

lodash实现深拷贝

lodash 是一个 JavaScript 实用工具库,提供了很多常用的工具函数。其中,cloneDeep 函数可以用于实现深拷贝:

import cloneDeep from 'lodash/cloneDeep' const obj1 = { a: 1, b: { c: 2 } } const obj2 = cloneDeep(obj1) console.log(obj2) // { a: 1, b: { c: 2 } } console.log(obj1 === obj2) // false

扩展运算符实现单层的深拷贝

扩展运算符可以用于复制数组和对象。但是,它只能复制对象的一层,因此它可以实现单层的深拷贝:

const arr1 = [1, 2, 3] const arr2 = [...arr1] console.log(arr2) // [1, 2, 3] console.log(arr1 === arr2) // false const obj1 = { a: 1, b: 2 } const obj2 = { ...obj1 } console.log(obj2) // { a: 1, b: 2 } console.log(obj1 === obj2) // false