天天看點

qbytearray的append是淺拷貝還是深拷貝_深拷貝 淺拷貝

(給前端大全加星标,提升前端技能)

轉自:掘金 - 尤雨溪的大迷弟

回顧一下老知識,記個筆記~

首先說下堆棧,基本資料類型與引用資料類型,深拷貝與淺拷貝與此相關。

一、基本資料類型 和 引用資料類型

1.變量類型分為兩類:

基本資料類型:

number

string

boolean

null

undefined

symbol

引用資料類型:統稱為

Object

類型,細分的話,有:

Object

Array

Date

Function

等。

2.存儲方式:

a.基本資料類型儲存在

記憶體,形式如下:棧記憶體中分别存儲着變量的辨別符以及變量的值。

例:

qbytearray的append是淺拷貝還是深拷貝_深拷貝 淺拷貝

b.引用資料類型儲存在

記憶體,形式如下:名存在棧記憶體中,值存在于堆記憶體中,但是棧記憶體會提供一個引用的位址指向堆記憶體中的值。

例:

qbytearray的append是淺拷貝還是深拷貝_深拷貝 淺拷貝

3.不同類型的複制方式:

a.基本資料類型:

qbytearray的append是淺拷貝還是深拷貝_深拷貝 淺拷貝

此時改變 a 變量的值,并不會影響 b 的值。

b.引用資料類型:

qbytearray的append是淺拷貝還是深拷貝_深拷貝 淺拷貝
二、淺拷貝 和 深拷貝

淺拷貝

:建立一個新的資料,這個資料有着原始資料屬性值的一份精确拷貝。如果屬性是基本類型,拷貝的就是基本類型的值,如果屬性是引用類型,拷貝的就是記憶體位址,是以如果其中一個資料改變了這個位址,就會影響到另一個資料。

可以說

淺拷貝

隻解決了資料第一層的問題,拷貝第一層的基本類型值,以及第一層的引用類型位址

深拷貝

:深拷貝會拷貝所有的屬性,并拷貝屬性指向的動态配置設定的記憶體。當對象和它所引用的對象一起拷貝時即發生深拷貝。深拷貝相比于淺拷貝速度較慢并且花銷較大。在堆中重新配置設定記憶體,擁有不同的位址,且值是一樣的,複制後的對象與原來的對象是完全隔離,互不影響。

三、實作深拷貝

1.資料隻有一層的時候:

Object.assign()

方法可以把任意多個的源對象自身的可枚舉屬性拷貝給目标對象,然後傳回目标對象。但是

Object.assign()

進行的是淺拷貝,拷貝的是對象的屬性的引用,而不是對象本身。當資料隻有一層的時候,是深拷貝。

相同的還有數組方法

slice

concat

,他們都為淺拷貝,當資料隻有一層的時候,可實作深拷貝的效果

例:

2.簡單的

遞歸

函數:

3.

JSON.parse(JSON.stringify())

用JSON.stringify将對象轉成JSON字元串,再用JSON.parse()把字元串解析成對象,一去一來,新的對象産生了,而且對象會開辟新的棧,實作深拷貝。

該方法有幾個缺陷:

1、會忽略

undefined

symbol

函數

,例:

2、對象循環引用時,會報錯。例:

3、new Date,轉換結果不正确

4、正則會被忽略

MDN的解釋,JSON.stringify() 将值轉換為相應的JSON格式:
  • 轉換值如果有 toJSON() 方法,該方法定義什麼值将被序列化。
  • 非數組對象的屬性不能保證以特定的順序出現在序列化後的字元串中。
  • 布爾值、數字、字元串的包裝對象在序列化過程中會自動轉換成對應的原始值。
  • undefined、任意的函數以及 symbol 值,在序列化過程中會被忽略(出現在非數組對象的屬性值中時)或者被轉換成 null(出現在數組中時)。函數、undefined 被單獨轉換時,會傳回 undefined,如JSON.stringify(function(){}) or JSON.stringify(undefined).
  • 對包含循環引用的對象(對象之間互相引用,形成無限循環)執行此方法,會抛出錯誤。
  • 所有以 symbol 為屬性鍵的屬性都會被完全忽略掉,即便 replacer 參數中強制指定包含了它們。
  • Date 日期調用了 toJSON() 将其轉換為了 string 字元串(同Date.toISOString()),是以會被當做字元串處理。
  • NaN 和 Infinity 格式的數值及 null 都會被當做 null。
  • 其他類型的對象,包括 Map/Set/WeakMap/WeakSet,僅會序列化可枚舉的屬性。

MDN位址:developer.mozilla.org/zh-CN/docs/…

網上看到的一個小題目:

個人了解:

var a = {n: 1}

棧中給a開辟了一個引用位址,指向堆中的對象

{n: 1}

var b = a

棧中給b開辟了一個引用位址,指向堆中的對象

{n: 1}

.

的優先級高于

=

,是以先執行

a.x

,堆記憶體中的

{n: 1}

就會變成

{n: 1, x: undefined}

,改變之後相應的

b.x

也變化了,因為指向的是同一個對象。

指派操作是從右到左,是以先執行

a = {n: 2}

,a的引用就被改變了,然後這個傳回值又指派給了

a.x

,需要注意的是這時候

a.x

是第一步中的

{n: 1, x: undefined}

那個對象,其實就是

b.x

,相當于

b.x = {n: 2}

- EOF -

推薦閱讀   點選标題可跳轉

1、一文讀懂 javascript 深拷貝與淺拷貝

2、面試題:如何實作一個深拷貝

3、一篇文章徹底說清 JS 的深拷貝/淺拷貝

覺得本文對你有幫助?請分享給更多人

推薦關注「前端大全」,提升前端技能

qbytearray的append是淺拷貝還是深拷貝_深拷貝 淺拷貝

點贊和在看就是最大的支援❤️