拷貝,理解為復(fù)制的意思寻馏,拷貝就是復(fù)制已經(jīng)存在的一個(gè)變量給另外一個(gè)變量棋弥,如:var a = 10; var b = a; b拷貝了a诚欠。那么 a 等不等于 b 呢顽染?要搞明白我們得先來(lái)了解下JavaScript的內(nèi)存管理機(jī)制漾岳。
JavaScript的內(nèi)存管理機(jī)制
內(nèi)存的周期是: 分配 -> 使用 -> 釋放
1. 分配:
變量被定義時(shí)候分配內(nèi)存,內(nèi)存存放又分為棧粉寞、堆尼荆、地址池。其中棧存放變量唧垦,且有固定的大小(基礎(chǔ)數(shù)據(jù))捅儒,堆存放復(fù)雜對(duì)象(引用數(shù)據(jù)類型),池存放常量振亮。
注意:JS不允許直接訪問(wèn)堆內(nèi)存中的位置巧还,因此我們不能直接操作對(duì)象的堆內(nèi)存空間。在操作對(duì)象時(shí)坊秸,實(shí)際上是在操作對(duì)象的引用而不是實(shí)際的對(duì)象麸祷。因此,引用類型的值都是按引用訪問(wèn)的妇斤。這里的引用摇锋,我們可以粗淺地理解為保存在棧內(nèi)存中的一個(gè)地址,該地址與堆內(nèi)存的實(shí)際值相關(guān)聯(lián)站超。
2. 使用:
對(duì)分配內(nèi)存進(jìn)行讀取與寫入的操作荸恕。如: var a = 1;a = 2; // 寫入內(nèi)存
3. 釋放:
所分配的內(nèi)存確實(shí)已經(jīng)不再需要了死相,釋放這過(guò)程涉及了垃圾回收機(jī)制融求,Javascript內(nèi)嵌了垃圾收集器,用來(lái)跟蹤內(nèi)存的分配和使用算撮,以便當(dāng)分配的內(nèi)存不再使用時(shí)生宛,自動(dòng)釋放它(如果沒(méi)有引用指向該對(duì)象(零引用),對(duì)象將被垃圾回收機(jī)制回收)肮柜。垃圾收集器會(huì)按照固定的時(shí)間間隔陷舅,或代碼執(zhí)行中預(yù)定的收集時(shí)間,周期性地執(zhí)行這一操作审洞。如下:
function fun1(){ var obj = {name:'ja'};}??var f1 = fun1(); obj?會(huì)被回收莱睁,因?yàn)関ar obj使用完
function fun2(){var obj = {name:'va'};return obj;}var f2 = fun2(); obj 不會(huì)被回收,因?yàn)楸籪2引用芒澜,f2屬于全局變量仰剿,頁(yè)面沒(méi)有卸載的情況下是不會(huì)被回收的
JavaScript的淺拷貝和深拷貝
基本數(shù)據(jù)類型不存在淺深拷貝問(wèn)題,引用類型存在
1. 淺拷貝:淺拷貝只復(fù)制指向某個(gè)對(duì)象的指針痴晦,而不復(fù)制對(duì)象本身南吮,新舊對(duì)象還是共享同一塊內(nèi)存,修改對(duì)象誊酌,原對(duì)象也會(huì)改變部凑。方法:Object.assign()(當(dāng)object只有一層的時(shí)候露乏,是深拷貝)、Array.prototype.concat()砚尽、Array.prototype.slice()
2. 深拷貝:深拷貝會(huì)另外創(chuàng)造一個(gè)一模一樣的對(duì)象施无,新對(duì)象跟原對(duì)象不共享內(nèi)存,修改新對(duì)象不會(huì)改到原對(duì)象必孤。方法:JSON.parse(JSON.stringify())(但不能處理函數(shù)、underfined)瑞躺、遍歷對(duì)象(只有一層對(duì)象直接循環(huán)敷搪,兩層對(duì)象則需要判斷類型)、遞歸(多層對(duì)象)
淺拷貝:
深拷貝:
遞歸拷貝:
var p = { "id":"007","name":"劉德華","wife":{"id":"008","name":"劉德的妻子","address":{"city":"北京","area":"海淀區(qū)"}}}
//寫函數(shù)
function copyObj(obj){let newObj={};for(let key in obj){if(typeof obj[key] =='object'){//如:key是wife,引用類型,那就遞歸newObj[key] = copyObj(obj[key])}else{//基本類型,直接賦值newObj[key] = obj[key];}}return newObj;}
let pNew = copyObj(p);pNew.wife.name="張三瘋";pNew.wife.address.city = "香港";console.log(pNew);console.log(p);