淺談js數(shù)組深拷貝和淺拷貝

1.背景介紹

什么是棧內(nèi)存和堆內(nèi)存?

JavaScript中的變量的存放有有原始值與引用值之分,原始值代表了原始的數(shù)據(jù)類型,如Undefined,Null,Number, String,Boolean類型的值;而Object,F(xiàn)unction,Array等類型的值便是引用值了。

棧內(nèi)存中存放的是存儲對象的地址,而堆內(nèi)存中存放的是存儲對象的具體內(nèi)容。對于原始類型的值而言 ,其地址和具體內(nèi)容都存在與棧內(nèi)存中;而基于引用類型的值,其地址存在棧內(nèi)存,其具體內(nèi)容存在堆內(nèi)存中。堆內(nèi)存 與棧內(nèi)存是有區(qū)別的,棧內(nèi)存運行效率比堆內(nèi)存高,空間相對堆內(nèi)存來說較小,反之則是堆內(nèi)存的特點。所以將構(gòu)造簡 單的原始類型值放在棧內(nèi)存中,將構(gòu)造復(fù)雜的引用類型值放在堆中而不影響棧的效率。

2.知識剖析

什么是深拷貝和淺拷貝?

淺拷貝:復(fù)制一份引用,所有引用對象都指向一份數(shù)據(jù),并且都可以修改這份數(shù)據(jù)。

深拷貝(復(fù)雜):復(fù)制變量值,對于非基本類型的變量,則遞歸至基本類型變量后,再復(fù)制。可以使用slice和concat方法。

SLICE和CONCAT使用方法

slice:

語法:arrayObject.slice(start,end)

該方法并不會修改數(shù)組,而是返回一個子數(shù)組。

start:必需。規(guī)定從何處開始選取。如果是負(fù)數(shù),那么它規(guī)定從數(shù)組尾部開始算起的位置。也就是說,-1 指最后一個元素,-2 指倒數(shù)第二個元素,以此類推。

end:可選。規(guī)定從何處結(jié)束選取。該參數(shù)是數(shù)組片斷結(jié)束處的數(shù)組下標(biāo)。如果沒有指定該參數(shù),那么切分的數(shù)組包含從 start 到數(shù)組結(jié)束的所有元素。如果這個參數(shù)是負(fù)數(shù),那么它規(guī)定的是從數(shù)組尾部開始算起的元素。

concat:

語法:arrayObject.concat(arrayX,arrayX,......,arrayX)

返回一個新的數(shù)組。該數(shù)組是通過把所有 arrayX 參數(shù)添加到 arrayObject 中生成的。如果要進行 concat() 操作的參 數(shù)是數(shù)組,那么添加的是數(shù)組中的元素,而不是數(shù)組。

arrayX:必需。該參數(shù)可以是具體的值,也可以是數(shù)組對象??梢允侨我舛鄠€。

3.常見問題

深拷貝和淺拷貝的運用環(huán)境。

4.解決方案

這個要看大家具體的應(yīng)用,注意到數(shù)組帶來的影響。

5.編碼實戰(zhàn)

淺拷貝的實現(xiàn),例如:

var arr = ["One","Two","Three"];

var arrto = arr; arrto[1] = "test”;

document.writeln("數(shù)組的原始值:" + arr + "

");//Export:數(shù)組的原始值:One,test,Three

document.writeln("數(shù)組的新值:" + arrto + "

");//Export:數(shù)組的新值:One,test,Three

深拷貝之slice:

var num = ["One","Two","Three"];

var newNum = num.slice(0);

newNum[1] = "haha";

document.writeln("數(shù)組的原始值:" + num + "

");//Export:數(shù)組的原始值:One,Two,Three

document.writeln("數(shù)組的新值:" + newNum + "

");//Export:數(shù)組的新值:One,haha,Three

深拷貝之concat

var arr = new Array(3)

arr[0] = "George"

arr[1] = "John"

arr[2] = "Thomas"

var arr2 = new Array(3)

arr2[0] = "James"

arr2[1] = "Adrew"

arr2[2] = "Martin"

document.write(arr.concat(arr2))//輸出:George,John,Thomas,James,Adrew,Martin;

6.擴展思考

對象的深拷貝

對象自己寫個迭代函數(shù)就好了,只需copy到最底層的比如如下代碼。

function deepCopy(obj,c) {

var c =c || {};

for(var i in obj) {

// 判斷屬性是否為對象,是的話就進一步展開

if (typeof(obj[i]) === 'object') {

// 遞歸拷貝

if (obj[i].constructor == Array){

c[i] = [];

deepCopy(obj[i],c[i]);

}

else {

c[i] = {};

deepCopy(obj[i],c[i]);

}

}

else {

c[i] = obj[i];

}

}

return c

};

7.參考文獻

參考一:JavaScript數(shù)組深拷貝和淺拷貝的兩種方法

參考二:原生js對象的淺拷貝和深拷貝的總結(jié)

8.更多討論

有被淺拷貝坑過的經(jīng)歷嗎?

Q1:簡述深拷貝和淺拷貝的最大不同?

A1:一個是復(fù)制粘貼(完全獨立),一個是創(chuàng)建快捷方式(一個內(nèi)存地址的不同引用)。

Q2:說出兩個深拷貝的js方法。

A2:SLICE()和CONCAT()

Q3:堆內(nèi)存與棧內(nèi)存的區(qū)別?

A3:堆內(nèi)存 與棧內(nèi)存是有區(qū)別的,棧內(nèi)存運行效率比堆內(nèi)存高,空間相對堆內(nèi)存來說較小,反之則是堆內(nèi)存的特點。所以將構(gòu)造簡 單的原始類型值放在棧內(nèi)存中,將構(gòu)造復(fù)雜的引用類型值放在堆中而不影響棧的效率。


如何實現(xiàn)數(shù)組深拷貝和淺拷貝?_騰訊視頻


PPT鏈接:PPT鏈接

視頻鏈接:https://v.qq.com/x/page/r0539yabtmb.html

今天的分享就到這里啦,歡迎大家點贊、轉(zhuǎn)發(fā)、留言、拍磚~

技能樹.IT修真院

“我們相信人人都可以成為一個工程師,現(xiàn)在開始,找個師兄,帶你入門,掌控自己學(xué)習(xí)的節(jié)奏,學(xué)習(xí)的路上不再迷?!?。

這里是技能樹.IT修真院,成千上萬的師兄在這里找到了自己的學(xué)習(xí)路線,學(xué)習(xí)透明化,成長可見化,師兄1對1免費指導(dǎo)??靵砼c我一起學(xué)習(xí)吧?!

歡迎進入修真之旅!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容