深拷貝和淺拷貝的區(qū)別
首先深復(fù)制和淺復(fù)制只針對(duì)像 Object, Array 這樣的復(fù)雜對(duì)象的。簡(jiǎn)單來(lái)說(shuō),淺復(fù)制只復(fù)制一層對(duì)象的屬性,而深復(fù)制則遞歸復(fù)制了所有層級(jí)。
1.淺拷貝: 將原對(duì)象或原數(shù)組的引用直接賦給新對(duì)象,新數(shù)組,新對(duì)象/數(shù)組只是原對(duì)象的一個(gè)引用 (let a =[1,2,3,4];let b=a;其實(shí)此時(shí)a與b指向同一塊內(nèi)存,b只是拷貝了a的引用,a與b任何一個(gè)改變,都會(huì)影響另一個(gè)值。a[0]=34;a===b;)
2.深拷貝: 創(chuàng)建一個(gè)新的對(duì)象和數(shù)組,將原對(duì)象的各項(xiàng)屬性的“值”(數(shù)組的所有元素)拷貝過(guò)來(lái),是“值”而不是“引用”
為什么要使用深拷貝?
我們希望在改變新的數(shù)組(對(duì)象)的時(shí)候,不改變?cè)瓟?shù)組(對(duì)象)
深拷貝的要求程度
我們?cè)谑褂蒙羁截惖臅r(shí)候,一定要弄清楚我們對(duì)深拷貝的要求程度:是僅“深”拷貝第一層級(jí)的對(duì)象屬性或數(shù)組元素,還是遞歸拷貝所有層級(jí)的對(duì)象屬性和數(shù)組元素?
改變?nèi)我庖粋€(gè)新對(duì)象/數(shù)組中的屬性/元素,???? 都不改變?cè)瓕?duì)象/數(shù)組
一、數(shù)組:對(duì)只有第一層級(jí)(且第一級(jí)元素是基本類型變量(如number,String,boolean)的簡(jiǎn)單數(shù)組)的數(shù)組做深拷貝?
1、for of 直接遍歷
var array = [1, 2, 3, 4];
function copy (array) {
?? let newArray = []
? for(let item of array) {
?? ? newArray.push(item);
?? }
?? return? newArray;
}
var copyArray = copy(array);
copyArray[0] = 100;
console.log(array); // [1, 2, 3, 4]
2. slice()
slice() 方法返回一個(gè)從已有的數(shù)組中截取一部分元素片段組成的新數(shù)組(不改變?cè)瓉?lái)的數(shù)組?。?/p>
用法:array.slice(start,end)start表示是起始元素的下標(biāo), end表示的是終止元素的下標(biāo)
當(dāng)slice()不帶任何參數(shù)的時(shí)候,默認(rèn)返回一個(gè)長(zhǎng)度和原數(shù)組相同的新數(shù)組
var array = [1, 2, 3, 4];
var copyArray = array.slice();
copyArray[0] = 100;
console.log(array); // [1, 2, 3, 4]
3. concat()
concat() 方法用于連接兩個(gè)或多個(gè)數(shù)組。( 該方法不會(huì)改變現(xiàn)有的數(shù)組,而僅僅會(huì)返回被連接數(shù)組的一個(gè)副本。)
用法:array.concat(array1,array2,......,arrayN)
var array = [1, 2, 3, 4];
var copyArray = array.concat();//實(shí)際上相當(dāng)于var copyArray = array.concat([]);
copyArray[0] = 100;
console.log(array); // [1, 2, 3, 4]
二、對(duì)象(只有一級(jí)適用,無(wú)嵌套時(shí))
1、Object.assign:用于對(duì)象的合并,將源對(duì)象(source)的所有可枚舉屬性,復(fù)制到目標(biāo)對(duì)象(target),并返回合并后的target
用法: Object.assign(target, source1, source2);所以 copyObj = Object.assign({}, obj);? 這段代碼將會(huì)把obj中的一級(jí)屬性都拷貝到 {}中,然后將其返回賦給copyObj
var obj = {
name:'小紅',
age:20
}
var copyObj =Object.assign({},obj)
copyObj.name='小明'
copyObj.age =24
console.log(obj)
console.log(copyObj)
//{name: "小紅", age: 20}
//{name: "小明", age: 24}
2、擴(kuò)展運(yùn)算符(...)用于取出參數(shù)對(duì)象的所有可遍歷屬性,拷貝到當(dāng)前對(duì)象之中
var obj = {
name:'小紅',
age:20
}
var copyObj ={...obj?}
copyObj.name='小明'
copyObj.age =24
console.log(obj)
console.log(copyObj)
三、萬(wàn)能(一級(jí)或多級(jí)均適用)
1.JSON.parse(JSON.stringify(XXXX))
var array = [
??? { number: 1 },
??? { number: 2 },
??? { number: 3 }
];
var copyArray = JSON.parse(JSON.stringify(array))
copyArray[0].number = 100;
console.log(array); //? [{number: 1}, { number: 2 }, { number: 3 }]
console.log(copyArray); // [{number: 100}, { number: 2 }, { number: 3 }]
2.手動(dòng)寫(xiě)遞歸,for in
var array = [
???{ number: 1 },
???{ number: 2 },
???{ number: 3 }
];
function copy (obj) {
??????? var newobj = obj.constructor === Array ? [] : {};
??????? if(typeof obj !== 'object'){
????????????return;
??????? }
??????? for(var i in obj){
???????????newobj[i] = typeof obj[i] === 'object' ?
???????????copy(obj[i]) : obj[i];
??????? }
??????? return newobj
}
var copyArray = copy(array)
copyArray[0].number = 100;
console.log(array); //? [{number: 1}, { number: 2 }, { number: 3 }]
console.log(copyArray); // [{number: 100}, { number: 2 }, { number: 3 }]
PS:constructor 與typeof
