JavaScript 浅拷贝和深拷贝
在JavaScript中,有两种方式可以拷贝对象: 浅拷贝 和 深拷贝 。理解这两种拷贝类型之间的差异在许多编程场景中非常重要,因为它们各有优势和劣势。
浅拷贝
浅拷贝是一种只拷贝一层深度的拷贝。换句话说,它会拷贝对象及其所有属性,但是任何嵌套的对象或数组仍然会引用原始对象相同的内存位置。这意味着如果对嵌套对象进行更改,它也会影响原始对象以及拷贝的对象。
下面是使用扩展运算符进行浅拷贝的示例:
const originalObject = { a: 1, b: { c: 2 } };
const shallowCopy = { ...originalObject };
在这个示例中, originalObject 有一个嵌套对象 b ,它有一个属性 c 。使用扩展运算符 … 创建了一个新对象 shallowCopy ,它是 originalObject 的浅拷贝。这意味着如果我们对 shallowCopy 进行修改,不会影响到 originalObject:
shallowCopy.a = 3; // Changes shallowCopy, but not originalObject
shallowCopy.b.c = 4; // Changes both shallowCopy and originalObject
正如您所见,改变shallowCopy上属性 a 的值不会影响到originalObject。然而,改变嵌套对象b上属性 c 的值会同时影响到shallowCopy和originalObject。
这是因为shallowCopy和originalObject都引用了同一个嵌套对象 b 。当我们在shallowCopy上修改 b 时,它会修改originalObject上的同一个对象。
深拷贝
深拷贝是创建一个新对象,并为其所有属性和嵌套的对象或数组分配新的内存空间的拷贝。这意味着如果您对拷贝的对象或其任何嵌套的对象或数组进行更改,不会影响到原始对象。
下面是使用JSON.parse()和JSON.stringify()方法对对象进行深拷贝的示例:
const originalObject = { a: 1, b: { c: 2 } };
const deepCopy = JSON.parse(JSON.stringify(originalObject));
在这个示例中,我们使用 JSON.stringify() 将 originalObject 转换为 JSON 字符串,然后使用 JSON.parse() 将该字符串转换回一个新的对象 deepCopy。它创建了 originalObject 的一个深拷贝。
现在,如果我们对 deepCopy 进行更改,不会影响到 originalObject:
deepCopy.a = 3; // Changes deepCopy, but not originalObject
deepCopy.b.c = 4; // Changes deepCopy, but not originalObject
如您所见,在deepCopy上更改属性a或嵌套对象b的值不会影响originalObject。这是因为deepCopy和originalObject有各自的内存位置,用于存储其所有属性和嵌套对象。
性能考虑
需要注意的是,深拷贝在性能方面可能比浅拷贝更昂贵。这是因为创建一个新对象并复制其所有属性和嵌套对象可能需要比简单地创建一个与原始对象具有对相同内存位置的引用的新对象需要更多的时间和内存。
在某些情况下,浅拷贝可能更高效和实用。然而,如果你需要确保对已拷贝对象的更改不会影响原始对象,那么深拷贝是必要的。
结论
在JavaScript中,有两种方式来拷贝对象:浅拷贝和深拷贝。浅拷贝创建一个新对象,并使用对原始对象相同内存位置的引用,而深拷贝创建一个新对象,并为其所有属性和嵌套对象或数组分配新的内存位置。
鉴于性能而言,浅拷贝可能更高效,但如果对已拷贝对象的更改会影响原始对象,则可能会导致意外行为。深拷贝确保对已拷贝对象的更改不会影响原始对象,但从性能方面来看可能更昂贵。
使用 JSON.parse() 和 JSON.stringify() 是创建对象深拷贝的简便方法,但在某些情况下可能无效。如果需要创建对象的深拷贝,使用 JSON.parse() 和 JSON.stringify() 是一种简便的选择。然而,如果被拷贝对象包含函数或循环引用,可能需要使用递归的深拷贝函数。