【JS】深拷貝與淺拷貝,實現深拷貝的幾種方法
本文部分內容來自https://www.cnblogs.com/echolun/p/7889848.html
昨天學習ES6的Object.assign()的時候,發現Object.assign進行的拷貝是淺拷貝,及只有第一層是深拷貝。若拷貝的屬性的值是物件的複合屬性,就只是拷貝過來一個引用。
const obj1 = {'a': {'b': 1}}
const obj2 = Object.assign({}, obj1)
obj1.a.b = 2
obj2.a.b // 2
那js的深拷貝和淺拷貝的區別是什麼呢
首先,先了解基本資料型別和引用資料型別。
基本資料型別:string、number、boolean、undefined、null
引用資料型別:object、array、function
(1)基本型別---名值儲存在棧記憶體中,例如 let a = 1
當b = a時:
棧記憶體開闢了一個新記憶體,所以修改a的值時,b的值並不會隨之變化。但這也算不上深拷貝,因為深拷貝本身只針對較為複雜的object型別資料。
(2)引用資料型別--名存在棧記憶體中,值存在於堆記憶體中,但是棧記憶體會提供一個引用的地址指向堆記憶體中的值
當b=a進行拷貝時,其實複製的是a的引用地址,而並非堆裡面的值
而當我們 a[0]=1 時進行陣列修改時,由於a與b指向的是同一個地址,所以自然b也受了影響,這就是所謂的淺拷貝了。
要是在堆記憶體中也開闢一個新的記憶體專門為b存放值,就像基本型別那樣,起步就達到深拷貝的效果了
所以我們應該怎麼實現深度拷貝呢
(1)遞迴去複製所有層級屬性
function deepClone(obj) {
let objClone = Array.isArray(obj) ? [] : {}
if (obj && typeof obj === 'object') {
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
// 判斷obj子元素是否為物件,如果是,遞迴複製
if (obj[key] && typeof obj[key] === 'object') {
objClone[key] = deepClone(obj[key])
} else {
objClone[key] = obj[key]
}
}
}
}
return objClone
}
let a = [1,2,3,4]
let b = deepClone(a) // [1,2,3,4]
a[0] = 2 // [2,2,3,4]
b // [1,2,3,4]
那是不是說slice方法也是深拷貝了,畢竟b也沒受a的影響,上面說了,深拷貝是會拷貝所有曾經的屬性,還是這個例子,我們把a改改
let a = [0,1,[2,3],4]
let b = a.slice()
a[0] = 1
a[2][0] = 1 // [1,1,[1,3],4]
b // [0,1,[1,3],4]
拷貝的不徹底啊,b物件的一級屬性確實不受影響了,但是二級屬性還是沒能拷貝成功,仍然脫離不了a的控制,說明slice根本不是真正的深拷貝。
這裡引用知乎問答裡面的一張圖
第一層的屬性確實深拷貝,擁有了獨立的記憶體,但更深的屬性卻仍然公用了地址,所以才會造成上面的問題。
同理,concat方法與slice也存在這樣的情況,他們都不是真正的深拷貝,這裡需要注意。
(2)用JSON物件的parse和stringify
function deepClone (obj) {
let _obj = JSON.stringify(obj)
let objClone = JSON.parse(_obj)
return objClone
}
let a = [0,1,[2,3],4]
let b = deepClone(a)
a[0] = 1
a[2][0] = 1 // [1,1,[1,3],4]
b // [0,1,[2,3],4]
(3)JQ的extend方法
JQ裡有extend方法也可以拷貝物件。
$.extend([deep ], target, object1 [, objectN ])
deep表示是否深拷貝,為true為深拷貝;為false,為淺拷貝。
target Object型別 目標物件,其他物件的成員屬性將被附加到該物件上。
object1 objectN可選。 Object型別 第一個以及第N個被合併的物件。
let a = [0,1,[2,3],4]
let b = $.extend(true, [], a)
a[0] = 1
a[2][0] = 1 // [1,1,[1,3],4]
b // [0,1,[2,3],4]
相關文章
- 淺談深拷貝與淺拷貝?深拷貝幾種方法。
- JS中的深淺拷貝以及實現深拷貝的幾種方法.JS
- JS深拷貝與淺拷貝JS
- js實現深拷貝和淺拷貝JS
- 淺拷貝與深拷貝的實現
- 淺拷貝與深拷貝
- js 深拷貝和淺拷貝JS
- js 淺拷貝和深拷貝JS
- 淺拷貝&深拷貝
- [JS系列二]談談深拷貝和淺拷貝,如何實現深拷貝JS
- js的深拷貝和淺拷貝JS
- 實現物件淺拷貝、深拷貝物件
- python深拷貝與淺拷貝Python
- Python淺拷貝與深拷貝Python
- 理解JS中的淺拷貝與深拷貝JS
- js之淺拷貝和深拷貝JS
- 淺探js深拷貝和淺拷貝JS
- 淺拷貝和深拷貝
- 深拷貝和淺拷貝
- 深拷貝、淺拷貝與Cloneable介面
- 談談深拷貝與淺拷貝
- 賦值、淺拷貝與深拷貝賦值
- React之淺拷貝與深拷貝React
- 深入淺出深拷貝與淺拷貝
- JavaScript中的淺拷貝與深拷貝JavaScript
- 【JavaScript】物件的淺拷貝與深拷貝JavaScript物件
- 深入淺出的“深拷貝與淺拷貝”
- iOS深拷貝和淺拷貝iOS
- JavaScript淺拷貝和深拷貝JavaScript
- Java深拷貝和淺拷貝Java
- 物件深拷貝和淺拷貝物件
- JavaScript深拷貝和淺拷貝JavaScript
- javascript 淺拷貝VS深拷貝JavaScript
- js 陣列的淺拷貝和深拷貝JS陣列
- python 指標拷貝,淺拷貝和深拷貝Python指標
- 圖解 Python 淺拷貝與深拷貝圖解Python
- 淺拷貝與深拷貝程式碼(javascript)JavaScript
- ES6深拷貝與淺拷貝