深拷貝與淺拷貝的區(qū)別栽连,實現(xiàn)深拷貝的幾種方法

本文出自【聽風是風

在項目中遇到一個頁面中保存的數(shù)組及對象在下個頁面需要調用以及返回時第一個頁面還需要用第一次生成的數(shù)據(jù),就使用到了深拷貝? ? 就對其進行了研究


如何區(qū)分深拷貝與淺拷貝侨舆,簡單點來說升酣,就是假設B復制了A,當修改A時态罪,看B是否會發(fā)生變化,如果B也跟著變了下面,說明這是淺拷貝复颈,拿人手短,如果B沒變,那就是深拷貝耗啦,自食其力凿菩。【講的通俗易懂】

我們來舉個淺拷貝例子:

let a=[0,1,2,3,4],

b=a;

console.log(a===b);

a[0]=1;

console.log(a,b);


明明b復制了a帜讲,為啥修改數(shù)組a衅谷,數(shù)組b也跟著變了

那么這里,就得引入基本數(shù)據(jù)類型與引用數(shù)據(jù)類型的概念了似将。

面試常問获黔,基本數(shù)據(jù)類型有哪些,number在验,string玷氏,boolean,null腋舌,undefined盏触,symbol以及未來ES10新增的BigInt(任意精度整數(shù))七類。

引用數(shù)據(jù)類型(Object類)有常規(guī)名值對的無序對象{a:1}块饺,數(shù)組[1,2,3]赞辩,以及函數(shù)等。

而這兩類數(shù)據(jù)存儲分別是這樣的:

a.基本類型--名值存儲在棧內(nèi)存中授艰,例如let a=1;

? ??????????

當你b=a復制時辨嗽,棧內(nèi)存會新開辟一個內(nèi)存,例如這樣:


所以當你此時修改a=2想诅,對b并不會造成影響召庞,因為此時的b已自食其力,翅膀硬了来破,不受a的影響了篮灼。當然,let a=1,b=a;雖然b不受a影響徘禁,但這也算不上深拷貝诅诱,因為深拷貝本身只針對較為復雜的object類型數(shù)據(jù)。

b.引用數(shù)據(jù)類型--名存在棧內(nèi)存中送朱,值存在于堆內(nèi)存中娘荡,但是棧內(nèi)存會提供一個引用的地址指向堆內(nèi)存中的值,我們以上面淺拷貝的例子畫個圖:


當b=a進行拷貝時驶沼,其實復制的是a的引用地址炮沐,而并非堆里面的值。


而當我們a[0]=1時進行數(shù)組修改時回怜,由于a與b指向的是同一個地址大年,所以自然b也受了影響,這就是所謂的淺拷貝了。


那翔试,要是在堆內(nèi)存中也開辟一個新的內(nèi)存專門為b存放值轻要,就像基本類型那樣,豈不就達到深拷貝的效果了


1.我們怎么去實現(xiàn)深拷貝呢垦缅,這里可以遞歸遞歸去復制所有層級屬性冲泥。

這么我們封裝一個深拷貝的函數(shù)(PS:只是一個基本實現(xiàn)的展示,并非最佳實踐)

function deepClone(obj){

? ? let objClone = Array.isArray(obj)?[]:{};

? ? if(obj &&typeofobj==="object"){

? ? ? ? for(keyin obj){

? ? ? ? ? ? if(obj.hasOwnProperty(key)){

? ? ? ? ? ? ? ? //判斷ojb子元素是否為對象壁涎,如果是凡恍,遞歸復制if(obj[key]&&typeofobj[key] ==="object"){

? ? ? ? ? ? ? ? ? ? objClone[key] = deepClone(obj[key]);

? ? ? ? ? ? ? ? }else{

? ? ? ? ? ? ? ? ? ? //如果不是,簡單復制objClone[key] = obj[key];

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? }

? ? }

? ? return objClone;

}? ?

let a=[1,2,3,4],

? ? b=deepClone(a);

a[0]=2;

console.log(a,b);

可以看到


跟之前想象的一樣粹庞,現(xiàn)在b脫離了a的控制咳焚,不再受a影響了。

這里再次強調庞溜,深拷貝革半,是拷貝對象各個層級的屬性,可以看個例子流码。JQ里有一個extend方法也可以拷貝對象又官,我們來看看

let a=[1,2,3,4],

? ? b=a.slice();

a[0]=2;

console.log(a,b);


那是不是說slice方法也是深拷貝了,畢竟b也沒受a的影響漫试,上面說了六敬,深拷貝是會拷貝所有層級的屬性,還是這個例子驾荣,我們把a改改

let a=[0,1,[2,3],4],

? ? ? ? b=a.slice();

a[0]=1;a[

2][0]=1;

console.log(a,b);


拷貝的不徹底啊外构,b對象的一級屬性確實不受影響了,但是二級屬性還是沒能拷貝成功播掷,仍然脫離不了a的控制审编,說明slice根本不是真正的深拷貝。

第一層的屬性確實深拷貝歧匈,擁有了獨立的內(nèi)存垒酬,但更深的屬性卻仍然公用了地址,所以才會造成上面的問題件炉。

同理勘究,concat方法與slice也存在這樣的情況,他們都不是真正的深拷貝斟冕,這里需要注意口糕。

2.除了遞歸,我們還可以借用JSON對象的parse和stringify

function deepClone(obj){

? ? let _obj = JSON.stringify(obj),

? ? ? ? objClone = JSON.parse(_obj);

? ? return objClone

}? ?

let a=[0,1,[2,3],4],

? ? b=deepClone(a);

a[0]=1;

a[2][0]=1;

console.log(a,b);


可以看到磕蛇,這下b是完全不受a的影響了走净。

附帶說下券时,JSON.stringify與JSON.parse除了實現(xiàn)深拷貝,還能結合localStorage實現(xiàn)對象數(shù)組存儲

3.除了上面兩種方法之外伏伯,我們還可以借用JQ的extend方法。

$.extend( [deep ], target, object1 [, objectN ] )

deep表示是否深拷貝捌袜,為true為深拷貝说搅,為false,則為淺拷貝

target?Object類型 目標對象虏等,其他對象的成員屬性將被附加到該對象上弄唧。

object1??objectN可選。 Object類型 第一個以及第N個被合并的對象霍衫。?

哈哈哈哈? 反正我明白了候引。。敦跌。澄干。

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市柠傍,隨后出現(xiàn)的幾起案子麸俘,更是在濱河造成了極大的恐慌,老刑警劉巖惧笛,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件从媚,死亡現(xiàn)場離奇詭異,居然都是意外死亡患整,警方通過查閱死者的電腦和手機拜效,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來各谚,“玉大人紧憾,你說我怎么就攤上這事〕氨蹋” “怎么了稻励?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長愈涩。 經(jīng)常有香客問我望抽,道長,這世上最難降的妖魔是什么履婉? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任煤篙,我火速辦了婚禮,結果婚禮上毁腿,老公的妹妹穿的比我還像新娘辑奈。我一直安慰自己苛茂,他們只是感情好,可當我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布鸠窗。 她就那樣靜靜地躺著妓羊,像睡著了一般。 火紅的嫁衣襯著肌膚如雪稍计。 梳的紋絲不亂的頭發(fā)上躁绸,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天,我揣著相機與錄音臣嚣,去河邊找鬼净刮。 笑死,一個胖子當著我的面吹牛硅则,可吹牛的內(nèi)容都是我干的淹父。 我是一名探鬼主播,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼怎虫,長吁一口氣:“原來是場噩夢啊……” “哼暑认!你這毒婦竟也來了?” 一聲冷哼從身側響起揪垄,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤穷吮,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后饥努,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體捡鱼,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年酷愧,在試婚紗的時候發(fā)現(xiàn)自己被綠了驾诈。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡溶浴,死狀恐怖乍迄,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情士败,我是刑警寧澤闯两,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站谅将,受9級特大地震影響漾狼,放射性物質發(fā)生泄漏。R本人自食惡果不足惜饥臂,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一逊躁、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧隅熙,春花似錦稽煤、人聲如沸核芽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽轧简。三九已至,卻和暖如春绿店,著一層夾襖步出監(jiān)牢的瞬間吉懊,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工假勿, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人态鳖。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓转培,卻偏偏與公主長得像,于是被迫代替她去往敵國和親浆竭。 傳聞我的和親對象是個殘疾皇子浸须,可洞房花燭夜當晚...
    茶點故事閱讀 42,792評論 2 345

推薦閱讀更多精彩內(nèi)容