淺談js數組深拷貝和淺拷貝

1.背景介紹

什么是棧內存和堆內存?

JavaScript中的變量的存放有有原始值與引用值之分,原始值代表了原始的數據類型,如Undefined,Null,Number, String,Boolean類型的值;而Object,Function,Array等類型的值便是引用值了。

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

2.知識剖析

什么是深拷貝和淺拷貝?

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

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

SLICE和CONCAT使用方法

slice:

語法:arrayObject.slice(start,end)

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

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

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

concat:

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

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

arrayX:必需。該參數可以是具體的值,也可以是數組對象。可以是任意多個。

3.常見問題

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

4.解決方案

這個要看大家具體的應用,注意到數組帶來的影響。

5.編碼實戰(zhàn)

淺拷貝的實現,例如:

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

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

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

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

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

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

深拷貝之slice:

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

var newNum = num.slice(0);

newNum[1] = "haha";

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

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

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

");//Export:數組的新值: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.擴展思考

對象的深拷貝

對象自己寫個迭代函數就好了,只需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數組深拷貝和淺拷貝的兩種方法

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

8.更多討論

有被淺拷貝坑過的經歷嗎?

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

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

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

A2:SLICE()和CONCAT()

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

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


如何實現數組深拷貝和淺拷貝?_騰訊視頻


PPT鏈接:PPT鏈接

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

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

技能樹.IT修真院

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

這里是技能樹.IT修真院,成千上萬的師兄在這里找到了自己的學習路線,學習透明化,成長可見化,師兄1對1免費指導。快來與我一起學習吧?!

歡迎進入修真之旅!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容