1. 拷貝的基本概念和必要性
在 JavaScript 中,數據類型分為基本數據類型(如?Number
、String
、Boolean
、Null
、Undefined
、Symbol
)和引用數據類型(如?Object
、Array
)。基本數據類型存儲的是值本身,而引用數據類型存儲的是內存地址。當需要對數據進行操作且不想影響原始數據時,就需要進行拷貝。
2. 淺拷貝(Shallow Copy)
概念
淺拷貝創建一個新對象,新對象的頂層屬性是原始對象屬性的副本,但如果原始對象的屬性是引用類型,新對象和原始對象會共享這些引用類型屬性的內存地址。也就是說,修改新對象中引用類型的屬性會影響原始對象中對應的屬性。
實現方式
- 擴展運算符(Spread Operator):常用于數組和對象的淺拷貝。
// 數組淺拷貝
const originalArray = [1, [2, 3]];
const shallowCopiedArray = [...originalArray];
shallowCopiedArray[1][0] = 9;
console.log(originalArray); // 輸出: [1, [9, 3]]// 對象淺拷貝
const originalObject = { a: 1, b: { c: 2 } };
const shallowCopiedObject = { ...originalObject };
shallowCopiedObject.b.c = 9;
console.log(originalObject.b.c); // 輸出: 9
Object.assign()
:用于將一個或多個源對象的所有可枚舉屬性復制到目標對象。
const original = { a: 1, b: { c: 2 } };
const shallowCopy = Object.assign({}, original);
shallowCopy.b.c = 9;
console.log(original.b.c); // 輸出: 9
Array.prototype.slice()
:常用于數組的淺拷貝。
const arr = [1, [2, 3]];
const newArr = arr.slice();
newArr[1][0] = 9;
console.log(arr); // 輸出: [1, [9, 3]]
3. 深拷貝(Deep Copy)
概念
深拷貝會遞歸地復制對象及其所有嵌套的屬性,創建一個完全獨立的新對象,新對象和原始對象在內存中沒有任何共享部分。修改新對象的任何屬性都不會影響原始對象。
實現方式
JSON.parse(JSON.stringify())
:這是一種簡單的深拷貝方法,但有局限性。它不能處理函數、Symbol
?類型的屬性、Date
?對象、RegExp
?對象等。
const original = { a: 1, b: { c: 2 } };
const deepCopy = JSON.parse(JSON.stringify(original));
deepCopy.b.c = 9;
console.log(original.b.c); // 輸出: 2
- 遞歸實現:自定義函數遞歸地復制對象和數組。
function deepClone(obj) {if (typeof obj !== 'object' || obj === null) {return obj;}let clone;if (Array.isArray(obj)) {clone = [];for (let i = 0; i < obj.length; i++) {clone[i] = deepClone(obj[i]);}} else {clone = {};for (let key in obj) {if (obj.hasOwnProperty(key)) {clone[key] = deepClone(obj[key]);}}}return clone;
}const original = { a: 1, b: { c: 2 } };
const deepCopy = deepClone(original);
deepCopy.b.c = 9;
console.log(original.b.c); // 輸出: 2