JS中的深拷貝與淺拷貝

在使用Vue做項(xiàng)目的時(shí)候播瞳,通常會(huì)有許多組件間傳遞對(duì)象的情況掸刊。如果只是簡單的賦值的話(淺拷貝),是很危險(xiǎn)的赢乓,因?yàn)槟悴恢朗裁辞闆r下這個(gè)值就被修改了忧侧,還一臉蒙蔽,所以我們需要進(jìn)行深拷貝牌芋。深拷貝和淺拷貝的概念蚓炬,需要一點(diǎn)數(shù)據(jù)結(jié)構(gòu)的知識(shí)去了解。

聲明一個(gè)object1對(duì)象
var object1 = {
  a:'a',
  b:'b' 
}

這時(shí)候我們來畫個(gè)內(nèi)存圖:聲明一個(gè)對(duì)象后在內(nèi)存內(nèi)某個(gè)地址上存入對(duì)象object的內(nèi)容躺屁,這個(gè)地址指向object1

image.png

然后把 對(duì)象1賦給對(duì)象2 var object2 = object1
這時(shí)候的內(nèi)存 我們來看一下


image.png

內(nèi)存內(nèi)同一個(gè)地址指向了兩個(gè)變量肯夏,其中一個(gè)變量內(nèi)容的改變都會(huì)影響這個(gè)地址內(nèi)存儲(chǔ)內(nèi)容的改變,這就是淺拷貝犀暑。
我們?cè)诮M件間傳遞對(duì)象的時(shí)候驯击,當(dāng)然不能進(jìn)行這么危險(xiǎn)的操作,應(yīng)該將內(nèi)存拷貝出去耐亏,使得另一個(gè)地址指向object2,這樣的拷貝就叫做深拷貝徊都。深拷貝之后兩個(gè)變量擁有相同的內(nèi)容,但是內(nèi)存地址不一樣广辰,互不影響暇矫。
那應(yīng)該怎么進(jìn)行深拷貝呢?择吊?

1袱耽、簡單粗暴的對(duì)象深拷貝

var object2 = JSON.parse( JSON.stringify(object1) )

簡單粗暴法沒有辦法深拷貝函數(shù),如果需要得自己封裝一個(gè)方法干发,去遞歸的深拷貝對(duì)象屬性朱巨。方法大家可以參考這篇文章 深入剖析 JavaScript 的深復(fù)制

2.在這里值得一提的是以下這種方式,這種方式看起來像是深拷貝枉长,其實(shí)是淺拷貝

function test() {
  'use strict';

  let obj1 = { a: 0 , b: { c: 0}};
  let obj2 = Object.assign({}, obj1);
  console.log(JSON.stringify(obj2)); // { a: 0, b: { c: 0}}
  
  obj1.a = 1;
  console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 0}}
  console.log(JSON.stringify(obj2)); // { a: 0, b: { c: 0}}
  
  obj2.a = 2;
  console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 0}}
  console.log(JSON.stringify(obj2)); // { a: 2, b: { c: 0}}
  
  obj2.b.c = 3;
  console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 3}}
  console.log(JSON.stringify(obj2)); // { a: 2, b: { c: 3}}

Object.assign()方法將一個(gè)的對(duì)象上的屬性枚舉復(fù)制給另一個(gè)對(duì)象冀续,但是當(dāng)object2的值改變時(shí)也會(huì)改變object1。感興趣的同學(xué)可以去看看object.assign()接口的源碼必峰,你會(huì)發(fā)現(xiàn)object.assign()只是深拷貝了源對(duì)象的頂層屬性洪唐,并沒有遞歸的去進(jìn)行深拷貝,當(dāng)源對(duì)象的屬性值是一個(gè)指向?qū)ο蟮囊煤鹨希仓豢截惸莻€(gè)引用值凭需。

3问欠、 ES8中提供的新方法

ES8中提供了一個(gè)新方法: Object.getOwnPropertyDescriptors。MDN描述:該方法返回指定對(duì)象上一個(gè)自有屬性對(duì)應(yīng)的屬性描述符粒蜈。(自有屬性指的是直接賦予該對(duì)象的屬性顺献,不需要從原型鏈上進(jìn)行查找的屬性)。應(yīng)用如下:

let a = {name:'lili',age:9,birth:'1995-10-13',sex:'gril'}

console.info(Object.getOwnPropertyDescriptors(a))

/* {name: {…}, age: {…}, birth: {…}, sex: {…}}
age
:
{value: 9, writable: true, enumerable: true, configurable: true}
birth
:
{value: "1995-10-13", writable: true, enumerable: true, configurable: true}
name
:
{value: "lili", writable: true, enumerable: true, configurable: true}
sex
:
{value: "gril", writable: true, enumerable: true, configurable: true}*/

結(jié)合Object.defineProperties()方法枯怖,該方法直接在一個(gè)對(duì)象上定義新的屬性或修改現(xiàn)有屬性注整,并返回該對(duì)象,可以實(shí)現(xiàn)對(duì)象的深拷貝,結(jié)合上一個(gè)例子:

let obj1 = { a: 0 , b: { c: 0}};
console.info(Object.getOwnPropertyDescriptors(obj1))
/*  {a:0,b:{c:0}}*/
obj1.b.c = 233;
obj1.a = 22;
console.info(Object.getOwnPropertyDescriptors(obj1))
/*  {a:22,b:{c:233}}*/
let obj2 = {}
Object.defineProperties(obj2,Object.getOwnPropertyDescriptors(obj1))
console.info( obj2 )
/*  {a:22,b:{c:233}}*/

4、 遞歸遍歷函數(shù)

function deep(obj){
if(typeof obj !== 'Object') return;
  var newObj = obj instanceof Array ? [] : {};
  for(var key in obj){ 
  newobj[key] = typeof obj === 'Object' ? deep(obj(key)): obj(key)
}
return newobj
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末度硝,一起剝皮案震驚了整個(gè)濱河市肿轨,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蕊程,老刑警劉巖椒袍,帶你破解...
    沈念sama閱讀 218,284評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異藻茂,居然都是意外死亡槐沼,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門捌治,熙熙樓的掌柜王于貴愁眉苦臉地迎上來岗钩,“玉大人,你說我怎么就攤上這事肖油〖嫦牛” “怎么了?”我有些...
    開封第一講書人閱讀 164,614評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵森枪,是天一觀的道長视搏。 經(jīng)常有香客問我,道長县袱,這世上最難降的妖魔是什么浑娜? 我笑而不...
    開封第一講書人閱讀 58,671評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮式散,結(jié)果婚禮上筋遭,老公的妹妹穿的比我還像新娘。我一直安慰自己暴拄,他們只是感情好漓滔,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著乖篷,像睡著了一般响驴。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上撕蔼,一...
    開封第一講書人閱讀 51,562評(píng)論 1 305
  • 那天豁鲤,我揣著相機(jī)與錄音秽誊,去河邊找鬼。 笑死琳骡,一個(gè)胖子當(dāng)著我的面吹牛锅论,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播日熬,決...
    沈念sama閱讀 40,309評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼肾胯!你這毒婦竟也來了竖席?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,223評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤敬肚,失蹤者是張志新(化名)和其女友劉穎毕荐,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體艳馒,經(jīng)...
    沈念sama閱讀 45,668評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡憎亚,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了弄慰。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片第美。...
    茶點(diǎn)故事閱讀 39,981評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖陆爽,靈堂內(nèi)的尸體忽然破棺而出什往,到底是詐尸還是另有隱情,我是刑警寧澤慌闭,帶...
    沈念sama閱讀 35,705評(píng)論 5 347
  • 正文 年R本政府宣布别威,位于F島的核電站,受9級(jí)特大地震影響驴剔,放射性物質(zhì)發(fā)生泄漏省古。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評(píng)論 3 330
  • 文/蒙蒙 一丧失、第九天 我趴在偏房一處隱蔽的房頂上張望豺妓。 院中可真熱鬧,春花似錦布讹、人聲如沸科侈。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽臀栈。三九已至,卻和暖如春挠乳,著一層夾襖步出監(jiān)牢的瞬間权薯,已是汗流浹背姑躲。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評(píng)論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留盟蚣,地道東北人黍析。 一個(gè)月前我還...
    沈念sama閱讀 48,146評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像屎开,于是被迫代替她去往敵國和親阐枣。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評(píng)論 2 355

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