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ī)定從何處開始選取哪轿。如果是負數(shù),那么它規(guī)定從數(shù)組尾部開始算起的位置翔怎。也就是說窃诉,-1 指最后一個元素杨耙,-2 指倒數(shù)第二個元素,以此類推飘痛。
end:可選珊膜。規(guī)定從何處結(jié)束選取。該參數(shù)是數(shù)組片斷結(jié)束處的數(shù)組下標宣脉。如果沒有指定該參數(shù)车柠,那么切分的數(shù)組包含從 start 到數(shù)組結(jié)束的所有元素。如果這個參數(shù)是負數(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)在開始宋欺,找個師兄,帶你入門胰伍,掌控自己學習的節(jié)奏齿诞,學習的路上不再迷茫”骂租。
這里是技能樹.IT修真院祷杈,成千上萬的師兄在這里找到了自己的學習路線,學習透明化菩咨,成長可見化吠式,師兄1對1免費指導(dǎo)〕槊祝快來與我一起學習吧?特占!