深拷貝與淺拷貝的區別和理解

2021-09-28 16:04:56 字數 3851 閱讀 5286

深拷使用

總結

一般拷貝的使用場景主要是,將物件或者陣列賦值到新的變數中。但是這樣就會出現乙個問題,當改變新的物件或陣列時,源陣列或物件也會發生改變,那麼這個時候要根據實際情況使用深度拷貝,還是淺拷貝,這裡不能一股腦的使用深度拷貝,畢竟深度拷貝對於效能的消耗還是蠻大的

對於像foreach、map、filter 如果操作的是基本資料型別則不會影響原始資料,一旦是物件、陣列這種引用型別的,那麼運算元據同樣會影響原始資料淺拷貝:將原物件或者原陣列直接賦給新的變數,這裡賦值的物件或者資料的引用,他們記憶體中指向的位址是乙個,所以新變數的值進行改變,其原物件或者陣列也會發生改變

深拷貝:將原物件或者原陣列的值賦給新的變數中,這裡是賦值的值,而不是引用,那麼當新變數的值發生改變,原物件或陣列不會發生改變

迴圈遍歷賦值

迴圈遍歷陣列進行賦值

let array =[1

,2,3

,4]let newarray =

;array.

foreach

((item)

=>

)newarray[0]

=10console.

log(

"原陣列==>>"

+array)

console.

log(

"新陣列==>>"

+newarray)

效果:

不是說是淺拷貝嗎,改變新陣列,原陣列會改變嗎,這裡為什麼並沒有達到預期?

**原因:**雖然原陣列是乙個引用型別,但因為遍歷陣列賦值的是數值型別(基本型別),所以並不會產生同乙個引用。所以才有上述的情況

直接進行賦值就會發生改變

let array =[1

,2,3

,4]let newarray =

;newarray=array;

newarray[0]

=10console.

log(

"原陣列==>>"

+array)

console.

log(

"新陣列==>>"

+newarray)

效果:

或者陣列物件

let array =[,

,,]let newarray =

; array.

foreach

(i =>

) newarray[0]

.num =

10 console.

log(

`原陣列==>>$`

) console.

log(

`新陣列==>>$`

)

可以看到這裡直接賦值,而因為產生同乙個引用,所以產生了原陣列改變的預期:

slice

slice() 方法可從已有的陣列中返回選定的元素。返回乙個新陣列

let array =[,

,,]let newarray = array.

slice()

; newarray[0]

.num =

10 console.

log(

`原陣列==>>$`

) console.

log(

`新陣列==>>$`

)

效果:

可以看到陣列物件情況下修改新陣列,原陣列會改變,該方法和第一種遍歷的方法是同樣的效果。其中如果數陣列數值非引用型別,就不會改變原陣列

concat

方法用於連線兩個或多個陣列。

該方法不會改變現有的陣列,而僅僅會返回被連線陣列的乙個副本。

let array =[,

,,]let newarray = array.

concat()

; newarray[0]

.num =

10 console.

log(

`原陣列==>>$`

) console.

log(

`新陣列==>>$`

預期和上述是一致的

object.assign

用於物件的合併,將源物件(source)的所有可列舉屬性,複製到目標物件(target)

注意,如果目標物件與源物件有同名屬性,或多個源物件有同名屬性,則後面的屬性會覆蓋前面的屬性。

let obj=

let newobj=object.

assign

(,obj)

; newobj.name=

"新拷貝"

console.

log(

`原陣列==>>$`

) console.

log(

`新陣列==>>$`

這裡的資料其實和上面方法的資料有個共同點,1層結構,那麼我改變新陣列或物件的值不會對源資料產生影響

多層:

let obj=

}let newobj=object.

assign

(,obj)

; newobj.name.nick=

"newnick"

console.

log(

`原陣列==>>$`

) console.

log(

`新陣列==>>$`

這裡其他的方式就不做贅述了json.parse(json.stringify())

使用json.stringify()轉成乙個字串,然後再用json.parse()轉成新的物件

但是這種方式只有可以轉成json物件的資料才可以使用,function等無法轉成json物件的就不能使用

強大的lodash庫

具體使用可以參考官方文件

深度遞迴

深度遞迴,遞迴每層,如果是引用型別那麼就去繼續遞迴,直到遇到是數值型別的,然後進行賦值,否則直接賦值

immutable

該庫提供了眾多的api,來實現深度拷貝

官網對於遍歷、slice、concat、es6擴充套件運算子(…)等等如果是拷貝的一層,那麼其實改變新陣列或物件是不會改變原陣列或物件,那麼這個時候對於只拷貝一層的可以在某種程度上稱之為深拷貝,如果陣列是陣列物件,超過一層或者物件超過一層,這個時候就是淺拷貝。

理解深拷貝和淺拷貝的區別

用擴充套件運算子深拷貝陣列 直接貼上 let arr 1 2,3 4,5 6 let arr1 arr arr1.push 7 console.log arr 1,2,3,4,5,6 console.log arr1 1,2,3,4,5,6,7 當陣列是一維陣列時,擴充套件運算子可以進行完全深拷貝,...

前端的深拷貝和淺拷貝 深拷貝與淺拷貝的區別

淺拷貝的方式 淺拷貝1 var obj var newobj obj newobj.name 李四 console.log obj console.log newobj 淺拷貝2 object.assgin 引數1 目標物件 引數2 任意多個物件 如果物件是多層的話 var obj var obj1...

理解「淺拷貝」和「深拷貝」

淺拷貝 將原物件 原陣列 的 引用 直接賦給新物件 新陣列 新物件 新陣列 是原物件 原陣列 的乙個引用。如果改變這個新物件 新陣列 原物件 原陣列 就會改變。深拷貝 將原物件的各項屬性的 值 陣列的所有元素 都拷貝給新物件 新陣列 是拷貝的 值 而不是 引用 為什麼要使用深拷貝?希望改變新物件 新...