一、淺拷貝
淺拷貝是指在JS中對象之間的引用關係,即拷貝源對象的引用,而不是源對象的副本。在淺拷貝中,源對象和目標對象會引用同一個內存地址中的內容,因此當源對象中的某個屬性值發生改變時,目標對象中的相應屬性值也會隨之改變。
// 淺拷貝示例 let obj1 = { a: 10, b: { c: 20 } }; let obj2 = Object.assign({}, obj1); obj1.b.c = 30; console.log(obj2.b.c); // 30
如上述代碼所示,當我們改變源對象obj1中的b.c屬性值時,因為obj2是淺拷貝得到的,所以其相應屬性值也被改變了。
然而,如果數值、字元串等基本數據類型的屬性值發生改變,淺拷貝則不會發生變化,因為基本數據類型的值是存儲在棧內存中的實際值,深淺拷貝都是拷貝了這個值。
二、深拷貝
深拷貝是指完全複製一個對象或多個嵌套對象的值,並將其複製到新的內存地址中。也就是說,源對象和目標對象是完全獨立的,互不關聯,互相之間的修改不會互相影響。
// 深拷貝示例 function deepClone(obj) { if (typeof obj !== 'object' || obj === null) { return obj; } // 根據obj的類型創建一個新的對象 let newObj = Array.isArray(obj) ? [] : {}; for (let key in obj) { // 判斷一個對象是否是自己的屬性 if (obj.hasOwnProperty(key)) { // 遞歸調用複製函數 newObj[key] = deepClone(obj[key]); } } return newObj; } let obj1 = { a: 10, b: { c: 20 } }; let obj2 = deepClone(obj1); obj1.b.c = 30; console.log(obj2.b.c); // 20
如上述代碼所示,當我們改變源對象obj1中的b.c屬性值時,目標對象obj2不會受到影響,因為它們是完全獨立的。
三、序列化和反序列化
JavaScript中的對象可以通過JSON.stringify()方法序列化為JSON格式的字元串,然後再通過JSON.parse()方法反序列化為新的對象。
// 序列化和反序列化示例 let obj1 = { a: 10, b: { c: 20 } }; let str = JSON.stringify(obj1); let obj2 = JSON.parse(str); obj1.b.c = 30; console.log(obj2.b.c); // 20
如上述代碼所示,在將序列化後的JSON字元串反序列化為新的對象後,它們是完全獨立的,相互之間不會產生影響。但是這種方法也有其缺點,因為在序列化和反序列化過程中,一些特殊的對象和屬性,如Date、RegExp、Function等,在序列化時無法得到正確的表現,因此可能會導致一些不可預測的結果。
四、使用第三方庫
除了上述三種方法外,還可以使用一些優秀的第三方庫提供的對象拷貝方法,如jQuery的$.extend()方法、lodash的_.cloneDeep()方法等,這些方法都針對不同的應用場景提供了完善的解決方案。
// underscore.js/lodash類庫提供深拷貝方法_.cloneDeep()的使用示例 let obj1 = { a: 10, b: { c: 20 } }; let obj2 = _.cloneDeep(obj1); obj1.b.c = 30; console.log(obj2.b.c); // 20
五、結語
JavaScript對象拷貝並不是一個簡單的問題,根據應用場景的不同,選擇不同的拷貝方式才能得到預期的結果。開發者需要多加註意,靈活選用不同的拷貝方法以滿足應用需求。
原創文章,作者:NCWUL,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/362681.html