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ù)組深拷貝和淺拷貝的兩種方法
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ù)雜的引用類型值放在堆中而不影響棧的效率。
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í)吧?!