摘要:二這么分的好處就是在于節(jié)省內(nèi)存資源,便于合理回收內(nèi)存詳解中的深淺復(fù)制有了上面的鋪墊,那么我們理解起深淺復(fù)制就變得容易的許多。
前言
對于前端開發(fā)來說,我們經(jīng)常能夠遇到的問題就是js的深淺復(fù)制問題,通常情況下我們解決這個問題的方法就是用JSON.parse(JSON.Stringify(xx))轉(zhuǎn)換或者用類似于Inmmutable這種第三方庫來進行深復(fù)制,但是我們還是要弄懂其中原理,這樣在開發(fā)過程中可以省掉很多的坑。
首先讓我們看幾個例子// eg1(操作原對象對復(fù)制對象無影響): var a = "a"; var b =a; a = "c"; console.log(b); // a // eg2(操作原對象對復(fù)制對象有影響): var a = { a:"a" }; var b =a; a.a = "c"; console.log(b); // {a:"c"} // eg3(操作原對象對復(fù)制對象無影響): var a = { a:"a" }; var b =a.a; a.a = "c"; console.log(b); // a // eg4(操作復(fù)制對象對原對象有影響): var a = { a:"a" }; var b = a b.b = "b"; console.log(a); // {a:"a",b:"b"} // eg5(操作復(fù)制對象對原對象沒有影響): var a = { a:"a" }; var b = a; b = { b:"b" } console.log(a); // {a:"a"}
想要理解上面例子發(fā)生的原因就要從數(shù)據(jù)類型和堆棧內(nèi)存開始說起
基本數(shù)據(jù)類型于引用數(shù)據(jù)類型js中存在著兩種數(shù)據(jù)類型:基本數(shù)據(jù)類型和引用數(shù)據(jù)類型;
基本數(shù)據(jù)類型包括:Number、String 、Boolean、Null和Undefined這些常見類型
引用數(shù)據(jù)類型包括: Object 、Array 、Function這些對象類型
在大多數(shù)編程語言中,都存在著這樣的兩個內(nèi)存空間一個是堆內(nèi)存(heap),另一個是棧內(nèi)存(stack)。
當(dāng)我們存儲一個基本數(shù)據(jù)類型的時候,我們直接放到棧內(nèi)存中。而當(dāng)我們存儲一個引用數(shù)據(jù)類型的時候,我們將實際內(nèi)容存儲在堆內(nèi)存當(dāng)中,同時在棧內(nèi)存中存放著該內(nèi)容的引用,也就是一個指針
為什么我們這么做呢?簡單來說有兩點,一是因為棧內(nèi)存中存放大小固定的數(shù)據(jù),即基本數(shù)據(jù)類型的數(shù)據(jù),同時引用數(shù)據(jù)類型的指針也是大小固定的,也可以放進棧內(nèi)存中,方便程序查找這個數(shù)據(jù);而堆內(nèi)存中存放的是大小不固定的數(shù)據(jù),所以適合存放引用數(shù)據(jù)類型。二這么分的好處就是在于節(jié)省內(nèi)存資源,便于os合理回收內(nèi)存
有了上面的鋪墊,那么我們理解起深淺復(fù)制就變得容易的許多。
首先我們要記住:當(dāng)我們復(fù)制一個基本數(shù)據(jù)類型的數(shù)據(jù)時,是新建一個數(shù)據(jù)同時存放到棧內(nèi)存中,而當(dāng)我們復(fù)制一個引用數(shù)據(jù)類型時,是復(fù)制這個引用數(shù)據(jù)類型的地址,存放到棧內(nèi)存中,此時堆內(nèi)存中并沒有任何變化
讓我們來看之前的例子
例一和例二就沒什么好說的了,我們從例三開始:
a.a是一個字符串類型,是基本類型,所以當(dāng)b復(fù)制的時候是直接復(fù)制了一個存放到棧內(nèi)存中,當(dāng)a改變時,對b沒有影響
例四:
a是一個對象,是引用數(shù)據(jù)類型,所以當(dāng)b復(fù)制的時候是復(fù)制了a的指針,當(dāng)對a和b操作時,仍然操作的是堆內(nèi)存中同一對象,所以a會發(fā)生改變
例五:
這個例子看似和上面的很像但實際有很大不同,b = {b:"b"}這個操作實際上是新建了一個對象
也就是說在堆內(nèi)存中新建了一個地方,來存放{b:"b"}同時將棧內(nèi)存中b原來存儲的指向a的指針指向了這個對象,多以a并未發(fā)生任何改變
https://segmentfault.com/a/11...(重點看這篇,寫的很好!)
http://blog.csdn.net/flyingpi...
https://www.cnblogs.com/cxyin...
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/107109.html
摘要:從而也引出了所謂的深淺復(fù)制問題。附注對于淺復(fù)制,其實還有其他的實現(xiàn)方式,比如數(shù)組中和方法,對于這些還是希望大家自己了解,本本主要針對深淺復(fù)制的實現(xiàn)原理進行解析。 前言 在之前寫繼承的過程談到了深淺復(fù)制的問題,因為有讀者反映到需要解析,趁今天周末寫一篇解析,今天的主體相對之前來說理解難度低一些,篇幅可能也比較短,諸君按需閱讀即可。 從兩種數(shù)據(jù)類型說起 在js中,變量的類型可以大致分成兩種...
摘要:中有三種數(shù)據(jù)結(jié)構(gòu)棧堆隊列。前端進擊的巨人一執(zhí)行上下文與執(zhí)行棧,變量對象中解釋執(zhí)行棧時,舉了一個乒乓球盒子的例子,來演示棧的存取方式,這里再舉個栗子搭積木。對于基本類型,棧中存儲的就是它自身的值,所以新內(nèi)存空間存儲的也是一個值。 面試經(jīng)常遇到的深淺拷貝,事件輪詢,函數(shù)調(diào)用棧,閉包等容易出錯的題目,究其原因,都是跟JavaScript基礎(chǔ)知識不牢固有關(guān),下層地基沒打好,上層就是豆腐渣工程,...
摘要:在之前的文章專題之?dāng)?shù)據(jù)類型和類型檢測中我有講過,中的數(shù)據(jù)類型分為兩種,基本數(shù)據(jù)類型和引用數(shù)據(jù)類型,基本數(shù)據(jù)類型是保存在棧的數(shù)據(jù)結(jié)構(gòu)中的是按值訪問,所以不存在深淺拷貝問題。 前言 在開發(fā)過程中,偶爾會遇到這種場景,拿到一個數(shù)據(jù)后,你打算對它進行處理,但是你又希望拷貝一份副本出來,方便數(shù)據(jù)對比和以后恢復(fù)數(shù)據(jù)。 那么這就涉及到了 JS 中對數(shù)據(jù)的深淺拷貝問題,所謂深淺拷貝,淺拷貝的意思就是,...
摘要:基本數(shù)據(jù)類型的復(fù)制很簡單,就是賦值操作,所以深淺拷貝也是針對,這類引用類型數(shù)據(jù)。它會拋棄對象的。另外,查資料過程中還看到這么一個詞結(jié)構(gòu)化克隆算法還有這一篇資料也有參考,也寫得比較詳細了的深淺拷貝 基本數(shù)據(jù)類型的復(fù)制很簡單,就是賦值操作,所以深淺拷貝也是針對Object,Array這類引用類型數(shù)據(jù)。 淺拷貝對于字符串來說,是值的復(fù)制,而對于對象來說則是對對象地址的復(fù)制;而深拷貝的話,它不...
摘要:深拷貝相比于淺拷貝速度較慢并且花銷較大。所以在賦值完成后,在棧內(nèi)存就有兩個指針指向堆內(nèi)存同一個數(shù)據(jù)。結(jié)果如下擴展運算符只能對一層進行深拷貝如果拷貝的層數(shù)超過了一層的話,那么就會進行淺拷貝那么我們可以看到和展開原算符對于深淺拷貝的結(jié)果是一樣。 JS中數(shù)據(jù)類型 基本數(shù)據(jù)類型: undefined、null、Boolean、Number、String和Symbol(ES6) 引用數(shù)據(jù)類型:...
閱讀 1480·2019-08-30 15:55
閱讀 1179·2019-08-30 15:52
閱讀 1301·2019-08-29 13:53
閱讀 1474·2019-08-29 11:19
閱讀 2980·2019-08-26 13:29
閱讀 538·2019-08-26 11:33
閱讀 2601·2019-08-23 17:20
閱讀 1032·2019-08-23 14:14