在 JavaScript 中,深拷貝(Deep Copy)?和?淺拷貝(Shallow Copy)?是兩種不同的對象復制方式,它們的區別主要體現在對嵌套對象的處理上。以下是它們的詳細對比及使用場景:
1.?淺拷貝(Shallow Copy)
-
定義:
-
淺拷貝只復制對象的第一層屬性,如果屬性是基本類型(如?
string
、number
、boolean
),則直接復制值;如果屬性是引用類型(如?object
、array
),則復制引用(內存地址)。 -
淺拷貝后的對象和原對象共享嵌套的引用類型數據。
-
-
實現方式:
-
使用?
Object.assign()
:const obj = { a: 1, b: { c: 2 } }; const shallowCopy = Object.assign({}, obj);
-
使用擴展運算符(
...
):const obj = { a: 1, b: { c: 2 } }; const shallowCopy = { ...obj };
-
-
特點:
-
修改淺拷貝對象的第一層屬性不會影響原對象。
-
修改淺拷貝對象的嵌套對象屬性會影響原對象。
-
-
示例:
const obj = { a: 1, b: { c: 2 } }; const shallowCopy = { ...obj };shallowCopy.a = 10; // 修改第一層屬性 shallowCopy.b.c = 20; // 修改嵌套對象屬性console.log(obj); // { a: 1, b: { c: 20 } } (嵌套對象被修改) console.log(shallowCopy); // { a: 10, b: { c: 20 } }
2.?深拷貝(Deep Copy)
-
定義:
-
深拷貝會遞歸復制對象的所有層級屬性,包括嵌套的引用類型數據。
-
深拷貝后的對象和原對象完全獨立,互不影響。
-
-
實現方式:
-
使用?
JSON.parse(JSON.stringify())
:const obj = { a: 1, b: { c: 2 } }; const deepCopy = JSON.parse(JSON.stringify(obj));
-
注意:這種方法無法復制函數、
undefined
、Symbol
?等特殊類型。
-
-
使用遞歸函數或工具庫(如 Lodash 的?
_.cloneDeep
):const _ = require('lodash'); const obj = { a: 1, b: { c: 2 } }; const deepCopy = _.cloneDeep(obj);
-
-
特點:
-
修改深拷貝對象的任何屬性都不會影響原對象。
-
深拷貝會完全復制對象的所有層級數據。
-
-
示例:
const obj = { a: 1, b: { c: 2 } }; const deepCopy = JSON.parse(JSON.stringify(obj));deepCopy.a = 10; // 修改第一層屬性 deepCopy.b.c = 20; // 修改嵌套對象屬性console.log(obj); // { a: 1, b: { c: 2 } } (原對象不受影響) console.log(deepCopy); // { a: 10, b: { c: 20 } }
3.?淺拷貝和深拷貝的區別
特性 | 淺拷貝(Shallow Copy) | 深拷貝(Deep Copy) |
---|---|---|
復制層級 | 只復制第一層屬性 | 遞歸復制所有層級屬性 |
嵌套對象 | 嵌套對象是引用(共享內存地址) | 嵌套對象是獨立的(不共享內存地址) |
性能 | 性能較高 | 性能較低(遞歸復制) |
實現方式 | Object.assign() 、擴展運算符 | JSON.parse(JSON.stringify()) 、遞歸函數、工具庫 |
適用場景 | 對象結構簡單,無需復制嵌套對象 | 對象結構復雜,需要完全獨立的對象 |
4.?如何選擇使用淺拷貝和深拷貝
-
使用淺拷貝的場景:
-
對象結構簡單,沒有嵌套對象或數組。
-
只需要復制第一層屬性,且不關心嵌套對象是否共享。
-
性能要求較高,且不需要完全獨立的對象。
-
-
使用深拷貝的場景:
-
對象結構復雜,包含嵌套對象或數組。
-
需要完全獨立的對象,修改拷貝對象不影響原對象。
-
不關心性能開銷,且需要完整的復制。
-
5.?總結
-
淺拷貝:
-
只復制第一層屬性,嵌套對象是引用。
-
適合簡單對象或性能敏感的場景。
-
-
深拷貝:
-
遞歸復制所有層級屬性,嵌套對象是獨立的。
-
適合復雜對象或需要完全獨立的場景。
-
根據實際需求選擇合適的拷貝方式,可以避免不必要的性能開銷和潛在的錯誤。