JS中的兩種數(shù)據(jù)類型及實(shí)現(xiàn)引用類型的深拷貝的方法
一.前言
我們知道,在JS中數(shù)據(jù)類型按照訪問(wèn)方式和存儲(chǔ)方式的不同可分為基本類型和引用類型。
基本類型
基本類型有String、Boolean、Number,Undefined、Null,這些基本類型都是按值傳遞的,也稱為值類型。
引用類型
引用類型有對(duì)象、數(shù)組、函數(shù),它們都是按引用訪問(wèn)的。
二.存儲(chǔ)方式區(qū)別
基本類型和引用類型由于兩者在內(nèi)存中存儲(chǔ)的方式不同,造成兩者訪問(wèn)的方式也不同。其中,基本類型存儲(chǔ)在內(nèi)存的棧中,是按值訪問(wèn);引用類型存儲(chǔ)在內(nèi)存的堆中,是按引用訪問(wèn)。可如下圖所示:
當(dāng)有
var n1 = 10; var n2 = 10; var arr1 = [1,2,3,4] var arr2 = [1,2,3,4]
其在內(nèi)存中存儲(chǔ)方式如圖:
值類型是在棧中直接保存的變量的實(shí)際值,而引用類型在棧中僅僅保存的是變量指向堆中的地址,從上圖中可以看出,值類型的變量n1和n2都是10,但是在棧中卻為這兩個(gè)變量分別開(kāi)辟了兩塊空間來(lái)存儲(chǔ),而引用類型的變量arr1和arr2也相同,但是在堆中僅僅開(kāi)辟了一塊內(nèi)存來(lái)存儲(chǔ),而在棧中存儲(chǔ)的是這兩個(gè)變量指向堆中的地址,這兩個(gè)變量都指向堆中的同一片地址。
三.拷貝區(qū)別
正是由于兩者在存儲(chǔ)方式上的不同,造成了兩者在拷貝時(shí)的差異。首先,先看兩段代碼:
var n1 = 10; //將n1拷貝給n2 var n2 = n1; n1 = 12; console.log(n1); console.log(n2);
先定義變量n1=10,然后將n1拷貝給n2,再接著改變n1的值為12,分別打印n1和n2的值,打印結(jié)果為:
從結(jié)果中我們可以看到,n1變?yōu)?2了,但是n2不受影響,依舊是10。
再看另外一段代碼:
var arr1 = [1,2,3,4] //將arr1拷貝給arr2 var arr2 = arr1; //向arr1中尾部添加一個(gè)元素5 arr1.push(5); console.log(arr1); console.log(arr2);
先定義數(shù)組arr1,然后將arr1拷貝給arr2,再接著向arr1中尾部追加一個(gè)元素,分別打印arr1和arr2的值,打印結(jié)果為:
從結(jié)果中我們可以看到:我們先將arr1拷貝給了arr2,但是當(dāng)我們改變arr1時(shí),arr2也跟著一起改變了。這印證了前文所說(shuō)的,arr1和arr2實(shí)際上是指向了內(nèi)存中的同一片地址,當(dāng)arr1發(fā)生變化時(shí),實(shí)際上是將指向的這片內(nèi)存地址中的數(shù)據(jù)變化了,而arr2也指向的是這片地址,所以arr2也會(huì)跟著變化。
上面代碼中的arr2=arr1,就是我們俗稱的淺拷貝,淺拷貝僅僅拷貝的是變量名,其在內(nèi)存的存儲(chǔ)沒(méi)有被拷貝,指向的還是同一片內(nèi)存地址,這就是造成了一個(gè)變化另外一個(gè)也跟著變化,這在日常開(kāi)發(fā)中不是我們想要的。
那如何實(shí)現(xiàn)真正的拷貝呢?
四.實(shí)現(xiàn)深拷貝
真正的拷貝,就是拷貝過(guò)后,arr1和arr2指向的不再是同一片內(nèi)存地址,而是分別指向各自的地址,這樣發(fā)生變化的時(shí)候就不會(huì)出現(xiàn)同時(shí)變化,這就是深拷貝。
下面我們封裝一個(gè)深拷貝函數(shù),來(lái)實(shí)現(xiàn)引用類型的深拷貝:
//參數(shù)p為原對(duì)象 //參數(shù)c為原對(duì)象的類型,若原對(duì)象為數(shù)組,則傳入c為[],若原對(duì)象是對(duì)象傳入c為{},也可不傳默認(rèn)為{} function deepCopy(p,c){ var c = c || {}; for(var i in p){ if(typeof p[i] === "object"){ c[i] = (p[i].constructor === Array)?[]:{}; deepCopy(p[i],c[i]) }else{ c[i] = p[i] } } return c; }
五.測(cè)試
//參數(shù)p為原對(duì)象 //參數(shù)c為原對(duì)象的類型,若原對(duì)象為數(shù)組,則傳入c為[],若原對(duì)象是對(duì)象傳入c為{},也可不傳默認(rèn)為{} function deepCopy(p,c){ var c = c || {}; for(var i in p){ if(typeof p[i] === "object"){ c[i] = (p[i].constructor === Array)?[]:{}; deepCopy(p[i],c[i]) }else{ c[i] = p[i] } } return c; } //定義數(shù)組arr1 var arr1 = [1,2,3,4] //將arr1拷貝給arr2 var arr2 = deepCopy(arr1,[]); //向arr1中尾部添加一個(gè)元素5 arr1.push(5); console.log('arr1:',arr1); console.log('arr2:',arr2);
測(cè)試結(jié)果:
結(jié)果中可以看到,arr1變化沒(méi)有引起arr2的變化,實(shí)現(xiàn)了真正的拷貝。
總結(jié)
以上所述是小編給大家介紹的JS中的兩種數(shù)據(jù)類型及實(shí)現(xiàn)引用類型的深拷貝的方法,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)歡迎給我留言,小編會(huì)及時(shí)回復(fù)大家的!
相關(guān)文章
JSONP獲取Twitter和Facebook文章數(shù)的具體步驟
這篇文章主要介紹了JSONP獲取Twitter和Facebook文章數(shù)的方法,需要的朋友可以參考下2014-02-02location.href 在IE6中不跳轉(zhuǎn)的解決方法與推薦使用代碼
在js中,我們經(jīng)常使用location.href來(lái)實(shí)現(xiàn)頁(yè)面的跳轉(zhuǎn),為了方便我們寫(xiě)成函數(shù)。下面就分別說(shuō)明下,下面的一些代碼的實(shí)現(xiàn)問(wèn)題。2010-07-07JavaScript數(shù)據(jù)結(jié)構(gòu)之鏈表的實(shí)現(xiàn)
鏈表是一種常見(jiàn)的數(shù)據(jù)結(jié)構(gòu)。它是動(dòng)態(tài)地進(jìn)行存儲(chǔ)分配的一種結(jié)構(gòu)。本文主要介紹JavaScript數(shù)據(jù)結(jié)構(gòu)中鏈表的實(shí)現(xiàn),具有很好的參考價(jià)值。下面跟著小編一起來(lái)看下吧2017-03-03前端頁(yè)面適配之postcss-px-to-viewport實(shí)現(xiàn)步驟
postcss-px-to-viewport是一個(gè)PostCSS插件,它可以將px單位轉(zhuǎn)換為視口單位(vw、vh?或?vmin),這篇文章主要給大家介紹了關(guān)于前端頁(yè)面適配之postcss-px-to-viewport的實(shí)現(xiàn)步驟,需要的朋友可以參考下2024-03-03網(wǎng)絡(luò)圖片延遲加載實(shí)現(xiàn)代碼 超越j(luò)query控件
原理是分段加載圖片,主要用于大型網(wǎng)站節(jié)省帶寬,可是他們提供的東西壓縮混淆看不清,還有的要基于什么雅虎的什么庫(kù),總之是很麻煩的,JQ的控件倒是夠清晰了,只是還是沒(méi)有達(dá)到節(jié)省網(wǎng)絡(luò)帶寬的效果2010-03-03基于Bootstrap漂亮簡(jiǎn)潔的CSS3價(jià)格表(附源碼下載)
該價(jià)格表基于Bootstrap網(wǎng)格系統(tǒng)來(lái)進(jìn)行布局,通過(guò)簡(jiǎn)單的CSS3代碼來(lái)美化價(jià)格表,樣式非常的時(shí)尚漂亮,且能在不同屏幕下展示良好的效果,需要的朋友可以參考下2017-02-02Bootstrap入門(mén)書(shū)籍之(零)Bootstrap簡(jiǎn)介
Bootstrap是一個(gè)用于快速開(kāi)發(fā) Web 應(yīng)用程序和網(wǎng)站的前端框架。Bootstrap 是基于 HTML、CSS、JAVASCRIPT 的。本文給大家介紹Bootstrap入門(mén)書(shū)籍之(零)Bootstrap簡(jiǎn)介,需要的朋友參考下2016-02-02javascript實(shí)現(xiàn)數(shù)字配對(duì)游戲的實(shí)例講解
下面小編就為大家分享一篇javascript實(shí)現(xiàn)數(shù)字配對(duì)游戲的實(shí)例講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2017-12-12