深拷貝與淺拷貝的理解及常用方法

深拷貝和淺拷貝的區(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ù)組元素?

怎么檢驗(yàn)深拷貝成功

改變?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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容