摘要:淺拷貝與深拷貝一數(shù)據(jù)類型數(shù)據(jù)分為基本數(shù)據(jù)類型,和對象數(shù)據(jù)類型。淺拷貝是按位拷貝對象,它會創(chuàng)建一個新對象,這個對象有著原始對象屬性值的一份精確拷貝。對于字符串?dāng)?shù)字及布爾值來說不是或者對象,會拷貝這些值到新的數(shù)組里。
淺拷貝與深拷貝
一、數(shù)據(jù)類型
數(shù)據(jù)分為基本數(shù)據(jù)類型(String, Number, Boolean, Null, Undefined,Symbol)和對象數(shù)據(jù)類型。
基本數(shù)據(jù)類型的特點:直接存儲在棧(stack)中的數(shù)據(jù)
引用數(shù)據(jù)類型的特點:存儲的是該對象在棧中引用,真實的數(shù)據(jù)存放在堆內(nèi)存里
引用數(shù)據(jù)類型在棧中存儲了指針,該指針指向堆中該實體的起始地址。當(dāng)解釋器尋找引用值時,會首先檢索其在棧中的地址,取得地址后從堆中獲得實體。
??
二、淺拷貝與深拷貝
深拷貝和淺拷貝是只針對Object和Array這樣的引用數(shù)據(jù)類型的。
深拷貝和淺拷貝的示意圖大致如下:
??
淺拷貝只復(fù)制指向某個對象的指針,而不復(fù)制對象本身,新舊對象還是共享同一塊內(nèi)存。但深拷貝會另外創(chuàng)造一個一模一樣的對象,新對象跟原對象不共享內(nèi)存,修改新對象不會改到原對象。
三、賦值和淺拷貝的區(qū)別
當(dāng)我們把一個對象賦值給一個新的變量時,賦的其實是該對象的在棧中的地址,而不是堆中的數(shù)據(jù)。也就是兩個對象指向的是同一個存儲空間,無論哪個對象發(fā)生改變,其實都是改變的存儲空間的內(nèi)容,因此,兩個對象是聯(lián)動的。
淺拷貝是按位拷貝對象,它會創(chuàng)建一個新對象,這個對象有著原始對象屬性值的一份精確拷貝。如果屬性是基本類型,拷貝的就是基本類型的值;如果屬性是內(nèi)存地址(引用類型),拷貝的就是內(nèi)存地址 ,因此如果其中一個對象改變了這個地址,就會影響到另一個對象。即默認拷貝構(gòu)造函數(shù)只是對對象進行淺拷貝復(fù)制(逐個成員依次拷貝),即只復(fù)制對象空間而不復(fù)制資源。
我們先來看兩個例子,對比賦值與淺拷貝會對原對象帶來哪些改變?
??
??
??
??
上面例子中,obj1是原始數(shù)據(jù),obj2是賦值操作得到,而obj3淺拷貝得到。我們可以很清晰看到對原始數(shù)據(jù)的影響,具體請看下表:
??
四、淺拷貝的實現(xiàn)方式
1.Object.assign()
Object.assign() 方法可以把任意多個的源對象自身的可枚舉屬性拷貝給目標(biāo)對象,然后返回目標(biāo)對象。但是 Object.assign()進行的是淺拷貝,拷貝的是對象的屬性的引用,而不是對象本身。
?
注意:當(dāng)object只有一層的時候,是深拷貝
??
2.Array.prototype.concat()
??
修改新對象會改到原對象:
??
3.Array.prototype.slice()
?
同樣修改新對象會改到原對象:
??
關(guān)于Array的slice和concat方法的補充說明:Array的slice和concat方法不修改原數(shù)組,只會返回一個淺復(fù)制了原數(shù)組中的元素的一個新數(shù)組。
原數(shù)組的元素會按照下述規(guī)則拷貝:
如果該元素是個對象引用(不是實際的對象),slice 會拷貝這個對象引用到新的數(shù)組里。兩個對象引用都引用了同一個對象。如果被引用的對象發(fā)生改變,則新的和原來的數(shù)組中的這個元素也會發(fā)生改變。
對于字符串、數(shù)字及布爾值來說(不是 String、Number 或者 Boolean 對象),slice 會拷貝這些值到新的數(shù)組里。在別的數(shù)組里修改這些字符串或數(shù)字或是布爾值,將不會影響另一個數(shù)組。
可能這段話晦澀難懂,我們舉個例子,將上面的例子小作修改:??
??
五、深拷貝的實現(xiàn)方式
JSON.parse(JSON.stringify())
??
??
原理: 用JSON.stringify將對象轉(zhuǎn)成JSON字符串,再用JSON.parse()把字符串解析成對象,一去一來,新的對象產(chǎn)生了,而且對象會開辟新的棧,實現(xiàn)深拷貝。
這種方法雖然可以實現(xiàn)數(shù)組或?qū)ο笊羁截?但不能處理函數(shù)
??
??
這是因為JSON.stringify() 方法是將一個JavaScript值(對象或者數(shù)組)轉(zhuǎn)換為一個 JSON字符串,不能接受函數(shù)
手寫遞歸方法
遞歸方法實現(xiàn)深度克隆原理:遍歷對象、數(shù)組直到里邊都是基本數(shù)據(jù)類型,然后再去復(fù)制,就是深度拷貝
??
函數(shù)庫lodash
該函數(shù)庫也有提供_.cloneDeep用來做 Deep Copy
??
喜歡的可以關(guān)注小編~
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/54879.html
摘要:所以,深拷貝是對對象以及對象的所有子對象進行拷貝實現(xiàn)方式就是遞歸調(diào)用淺拷貝對于深拷貝的對象,改變源對象不會對得到的對象有影響。 為什么會有淺拷貝與深拷貝什么是淺拷貝與深拷貝如何實現(xiàn)淺拷貝與深拷貝好了,問題出來了,那么下面就讓我們帶著這幾個問題去探究一下吧! 如果文章中有出現(xiàn)紕漏、錯誤之處,還請看到的小伙伴多多指教,先行謝過 以下↓ 數(shù)據(jù)類型在開始了解 淺拷貝 與 深拷貝 之前,讓我們先...
摘要:所以,深拷貝是對對象以及對象的所有子對象進行拷貝實現(xiàn)方式就是遞歸調(diào)用淺拷貝對于深拷貝的對象,改變源對象不會對得到的對象有影響。 上一篇 JavaScript中的繼承 前言 文章開始之前,讓我們先思考一下這幾個問題: 為什么會有淺拷貝與深拷貝 什么是淺拷貝與深拷貝 如何實現(xiàn)淺拷貝與深拷貝 好了,問題出來了,那么下面就讓我們帶著這幾個問題去探究一下吧! 如果文章中有出現(xiàn)紕漏、錯誤之處...
摘要:深拷貝與淺拷貝的出現(xiàn),就與這兩個數(shù)據(jù)類型有關(guān)。這時,就需要用淺拷貝來實現(xiàn)了。數(shù)據(jù)一但過多,就會有遞歸爆棧的風(fēng)險。這個方法是在解決遞歸爆棧問題的基礎(chǔ)上,加以改進解決循環(huán)引用的問題。但如果你并不想保持引用,那就改用用于解決遞歸爆棧即可。 前言 這是前端面試題系列的第 9 篇,你可能錯過了前面的篇章,可以在這里找到: 數(shù)組去重(10 種濃縮版) JavaScript 中的事件機制(從原生到...
摘要:一淺拷貝與深拷貝區(qū)別淺拷貝只能實現(xiàn)淺層次的值復(fù)制和路徑復(fù)制,當(dāng)值為引用類型是傳遞過去的是一個地址,當(dāng)改變其中一值時,兩者都會發(fā)生改變。 一、淺拷貝與深拷貝區(qū)別 1.淺拷貝只能實現(xiàn)淺層次的值復(fù)制和路徑復(fù)制,當(dāng)值為引用類型是傳遞過去的是一個地址,當(dāng)改變其中一值時,兩者都會發(fā)生改變。 2.深拷貝會對對象進行深層次的復(fù)制,也就是當(dāng)值為引用類型時會循環(huán)直到值為基本值類型時才會復(fù)制。 3.實現(xiàn)jQ...
摘要:也就是說,深拷貝與淺拷貝最主要的區(qū)別在引用類型的拷貝上。方法二遞歸拷貝深拷貝與淺拷貝相比不就是多拷貝幾層的事嘛,這不就是遞歸常干的事嘛。 什么是淺拷貝和深拷貝 淺拷貝 淺拷貝:將一個對象自身的屬性拷貝給另一個對象,如果源對象的屬性是基本類型則直接進行值賦值,如果是引用類型則進行引用賦值,也就是說只進行一層賦值。 深拷貝 深拷貝:將一個對象自身的屬性拷貝給另一個對象,如果源對象的屬性是基...
閱讀 2798·2023-04-26 01:47
閱讀 3603·2023-04-25 23:45
閱讀 2487·2021-10-13 09:39
閱讀 621·2021-10-09 09:44
閱讀 1813·2021-09-22 15:59
閱讀 2793·2021-09-13 10:33
閱讀 1738·2021-09-03 10:30
閱讀 670·2019-08-30 15:53