js淺克隆與深克隆

什么是深克隆姓建,什么是淺克隆呢诞仓?

首先,克隆只針對對象引瀑、數(shù)組狂芋、函數(shù)等復(fù)雜數(shù)據(jù)。
淺克隆就是將棧內(nèi)存中的引用復(fù)制一份憨栽,賦給一個新的變量帜矾,本質(zhì)上兩個指向堆內(nèi)存中的同一地址,內(nèi)容也相同屑柔,其中一個變化另一個內(nèi)容也會變化(根本上改變的是同一個對象)屡萤。

深克隆就是創(chuàng)建一個新的空對象,開辟一塊內(nèi)存掸宛,然后將原對象中的數(shù)據(jù)全部復(fù)制過去死陆,完全切斷兩個對象間的聯(lián)系。

例如:

var a = new Array;
a[0] = "小明";
a[1] = "小紅";
a[2] = "小光";
b = a;
alert(b);

這里簡單定義了一個數(shù)組a,然后加入三個元素措译,再把a賦給變量b别凤,輸入b后發(fā)現(xiàn)內(nèi)容是a的內(nèi)容。這里涉及到一些內(nèi)存位置的內(nèi)容领虹,簡單說說规哪。這里創(chuàng)建出的數(shù)組(array)被放在堆內(nèi)存中,而a,b兩個引用都是在棧內(nèi)存中塌衰。array包含了三個元素诉稍,a和b則僅僅是一個地址,指向了array最疆,和C語言中的指針非常相似杯巨。這里就是一個簡單的淺克隆的例子,把數(shù)組array的引用復(fù)制一份給b努酸,讓兩個變量都指向array服爷。這時候任意一個引用對array做出的修改都會折射到另一個引用上。

明白了淺克隆获诈,這里也解釋一下為什么開始說深淺克隆只針對對象數(shù)組函數(shù)等层扶。先說說棧,棧內(nèi)存有很多優(yōu)點烙荷,比如讀取速度很快,僅次于寄存器檬寂;棧內(nèi)存數(shù)據(jù)可以共享终抽。但也有缺點,棧內(nèi)存大小和生存期必須是確定的桶至,缺乏靈活性昼伴。而因為基本變量(js的原始值undefined,null,number,string,boolean 類型)一般所占內(nèi)存一半較小且大小固定,所以一般放在棧中镣屹,如果放在堆中可能查找耗時較多圃郊。堆內(nèi)存中的數(shù)組、函數(shù)女蜈、對象等持舆,一方面可能較大,另一方面不確定大小伪窖,所以不能放在棧中逸寓,只能在堆里面,由棧內(nèi)存中的句柄(也可以叫指針)加以引用操作覆山。深淺克隆只能針對在堆內(nèi)存中的竹伸,有句柄引用的復(fù)雜對象。

深克隆本質(zhì)上是創(chuàng)造一個完全一樣的對象簇宽,這里簡單介紹兩種js的deepClone方法勋篓。

一吧享、遞歸完成深克隆

例如:

function deepClone(arr) {
  if (typeof arr != "object") {
    return arr;
  }
  var result = {};
  for (var i in arr) {
    result[i] = deepClone(arr[i]);
  }
  return result;
}

首先判斷元素是否是object,不是打哪兒來回哪兒去譬嚣,然后創(chuàng)建一個對象賦給result钢颂。然后遍歷arr中所有的元素,遞歸判斷是否是深層對象孤荣,不是返回賦給result甸陌。這樣就實現(xiàn)了深克隆。下面測試一下:

var a = {
  name:"小明",
  age:"12",
  sister:{
    name:"小美",
    age:"10"
  }
}


var arrTwo = arrOne;
var arrThree = deepClone(a);
arrThree.name = "小光";
arrThree.object.name = "小雅";

console.log(arrTwo);
console.log(arrThree);

輸出結(jié)果:

Object:
    name:"小明",
    age:"12",
    Object:
        name:"小美",
         age:"10"

Object:
    name:"小光",
    age:"12",
    Object:
        name:"小雅",
         age:"10"

可以看到在對原數(shù)組操作時盐股,克隆返回的數(shù)組內(nèi)容不會改變钱豁。兩個數(shù)組是完全不同的兩個對象,在堆內(nèi)存中各占一塊疯汁,沒有關(guān)聯(lián)牲尺。

二、利用JSON

利用json就能輕松搞定:

var a = {
  name:"小明",
  age:"12",
  sister:{
    name:"小美",
    age:"10"
  }
}


var arrTwo = arrOne;
var arrThree = deepClone(a);  //12行
arrThree.name = "小光";
arrThree.object.name = "小雅";

console.log(arrTwo);
console.log(arrThree);

把12行稍微改動一下:

var a = {
  name:"小明",
  age:"12",
  sister:{
    name:"小美",
    age:"10"
  }
}


var arrTwo = arrOne;
var arrThree = JSON.parse(JSON.stringify(arrTwo));  //12行
arrThree.name = "小光";
arrThree.object.name = "小雅";

console.log(arrTwo);
console.log(arrThree);

parse和stringify方法:

JSON.parse() :
Parse a string as JSON, optionally transform the produced value and its properties, and return the value.

JSON.stringify() :
Return a JSON string corresponding to the specified value, optionally including only certain properties or replacing property values in a user-defined manner.
這里是摘自dash文檔的對兩個方法的介紹幌蚊,parse方法用于將字符串解析為 JSON谤碳,可以任意轉(zhuǎn)換生成的值及其屬性,并返回值溢豆。sretingify方法用于從一個對象中解析出json字符串蜒简。

意思就是將一個對象先解析為json對象,然后再解析成object對象漩仙,變來變?nèi)ロ樀绖?chuàng)建個對象完成復(fù)制搓茬。

總結(jié)

所謂深克隆就是創(chuàng)造一個完全一樣的對象,將原對象的的所有元素拷貝過來即可队他。

淺克隆就是復(fù)制一份引用卷仑,所有引用指向同一份數(shù)據(jù)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末麸折,一起剝皮案震驚了整個濱河市锡凝,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌垢啼,老刑警劉巖窜锯,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異膊夹,居然都是意外死亡衬浑,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進店門放刨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來工秩,“玉大人,你說我怎么就攤上這事≈遥” “怎么了浪听?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長眉菱。 經(jīng)常有香客問我迹栓,道長,這世上最難降的妖魔是什么俭缓? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任克伊,我火速辦了婚禮,結(jié)果婚禮上华坦,老公的妹妹穿的比我還像新娘愿吹。我一直安慰自己,他們只是感情好惜姐,可當(dāng)我...
    茶點故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布犁跪。 她就那樣靜靜地躺著,像睡著了一般歹袁。 火紅的嫁衣襯著肌膚如雪坷衍。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天条舔,我揣著相機與錄音枫耳,去河邊找鬼。 笑死孟抗,一個胖子當(dāng)著我的面吹牛嘉涌,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播夸浅,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼扔役!你這毒婦竟也來了帆喇?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤亿胸,失蹤者是張志新(化名)和其女友劉穎坯钦,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體侈玄,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡婉刀,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了序仙。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片突颊。...
    茶點故事閱讀 40,503評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出律秃,到底是詐尸還是另有隱情爬橡,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布棒动,位于F島的核電站糙申,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏船惨。R本人自食惡果不足惜柜裸,卻給世界環(huán)境...
    茶點故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望粱锐。 院中可真熱鬧疙挺,春花似錦、人聲如沸卜范。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽海雪。三九已至锦爵,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間奥裸,已是汗流浹背险掀。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留湾宙,地道東北人樟氢。 一個月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像侠鳄,于是被迫代替她去往敵國和親埠啃。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,512評論 2 359

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

  • 因為近日的項目需要用到對數(shù)組做深克隆伟恶,所以做一個簡要介紹與總結(jié)碴开。 一開始聽說這個概念的時候嚇一跳,覺得高深莫測博秫,有...
    FJW135閱讀 687評論 0 1
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理潦牛,服務(wù)發(fā)現(xiàn),斷路器挡育,智...
    卡卡羅2017閱讀 134,701評論 18 139
  • *面試心聲:其實這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個offer,總結(jié)起來就是把...
    Dove_iOS閱讀 27,161評論 30 470
  • (酒吧包廂里) “今天怎么進來了巴碗?”葉微霞斜靠在沙發(fā)上,打趣地說即寒。 “外頭太吵橡淆≌儇” “哦~”葉微霞勾起嘴角“維軒還...
    方木桃景閱讀 137評論 0 1
  • 注定,他的墳?zāi)褂肋h是一個濕潤的土丘明垢。 注定蚣常,他的墳?zāi)褂肋h長不出一朵用于點綴寂寞的野花,哪怕一朵痊银。 我站在幽暗的黃昏...
    寒揚閱讀 453評論 0 37