本文檔適用于有一定經(jīng)驗(yàn)的開(kāi)發(fā)者锉屈。我們默認(rèn)你已經(jīng)掌握了指針的概念(也可稱為地址) 荤傲,如果你是新手,你可能需要先了解 指針的概念
我們?cè)贘S中經(jīng)常需要復(fù)制一個(gè)對(duì)象或數(shù)組颈渊。
當(dāng)我們直接使用
=賦值時(shí)
遂黍,我們實(shí)際只賦值了這個(gè)對(duì)象的指針。這種情況 連拷貝都算不上俊嗽。
例:如下我們給array2賦值雾家,實(shí)際是賦值給array2一個(gè)指針,指針指向array1指向的數(shù)組绍豁。因此我們編輯 array2 時(shí)芯咧,array1也會(huì)變。
let array1 = [1,2,3]
let array2 = array1
array2[0] = 100
/*
array1
>(3) [100, 2, 3]
array2
(3) [100, 2, 3]
*/
淺拷貝可以將數(shù)組(對(duì)象)的第一層拷貝下來(lái)竹揍。
ES6給我們提供了兩個(gè)方便的淺拷貝方法:
Array.from()與Object.assign()
例:下面我們通過(guò)Array.from()
對(duì)array3進(jìn)行淺拷貝唬党。我們可以看出,當(dāng)我們修改array4的普通元素時(shí)鬼佣,array3已經(jīng)不會(huì)隨著改變了驶拱。但是淺拷貝只是拷貝了第一層的元素,如果第一層元素含有對(duì)象(數(shù)組)晶衷,我們只拷貝一個(gè)指針(地址)蓝纲。array4通過(guò)這個(gè)指針(地址)訪問(wèn)的對(duì)象將是與array3是相同的。
let array3 = [1,2,3,{a:1,b:2,c:3}]
let array4 = Array.from(array3)
array4[0] = 100
array4[3].a = 100
/*
array3
>(4) [1, 2, 3, {a: 100, b: 2, c: 3}]
array4
>(4) [100, 2, 3, {a: 100, b: 2, c: 3}]
*/
目前JS常見(jiàn)的深拷貝有兩種方式
晌纫。第一種種是兩次JSON化:
let array6 = JSON.parse(JSON.stringfiy(array5))
這種方法很簡(jiǎn)單税迷,但是當(dāng)元素含有undefined
或正則表達(dá)式
時(shí)函數(shù)會(huì)拋出異常。
第二種深拷貝是逐層遍歷逐一賦值的方法锹漱,要麻煩一些箭养,但是沒(méi)有第一種的缺點(diǎn)。
目前哥牍,這兩種以外的拷貝方式都是淺拷貝毕泌。例如for...of遍歷中的item實(shí)際是對(duì)對(duì)象元素的淺拷貝。
// 例:逐層遍歷逐一賦值的深拷貝工具類
class deepCopy {
static toRawType(value) {
return Object.prototype.toString.call(value).slice(8, -1);
}
/* 已整合在tools中 */
static copy(obj) {
let emptyObject = null;
if (this.toRawType(obj) == 'Object') {
emptyObject = {};
}
else if (this.toRawType(obj) == 'Array') {
emptyObject = [];
}
else {
return obj;
}
for (let key in obj) {
if (typeof obj[key] != 'object' || obj[key] == null) {
emptyObject[key] = obj[key];
}
else {
emptyObject[key] = this.copy(obj[key]);
}
}
return emptyObject;
}
}
let array5 = [1,2,3,{a:1,b:2,c:3}]
let array6 = deepCopy.copy(array5)
array6[3].a = 100
/*
array3
>(4) [1, 2, 3, {a: 1, b: 2, c: 3}]
array4
>(4) [1, 2, 3, {a: 100, b: 2, c: 3}]
*/