JS淺克隆與深克隆

因?yàn)榻盏捻?xiàng)目需要用到對數(shù)組做深克隆,所以做一個(gè)簡要介紹與總結(jié)。

一開始聽說這個(gè)概念的時(shí)候嚇一跳,覺得高深莫測,有點(diǎn)怕怕啊。完了了解一下,哦,原來就這玩意啊~~~

那么什么是深克隆,什么是淺克隆呢?

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

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

還是show code to 表達(dá):

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

這里簡單定義了一個(gè)數(shù)組a,然后加入三個(gè)元素,再把a(bǔ)賦給變量b,輸入b后發(fā)現(xiàn)內(nèi)容是a的內(nèi)容。這里涉及到一些內(nèi)存位置的內(nèi)容,簡單說說。這里創(chuàng)建出的數(shù)組(姑且叫他array)被放在堆內(nèi)存中,而a,b兩個(gè)引用都是在棧內(nèi)存中。array包含了三個(gè)元素,a和b則僅僅是一個(gè)地址,指向了array,和c語言中的指針非常相似。這里就是一個(gè)簡單的淺克隆的例子,把數(shù)組array的引用復(fù)制一份給b,讓兩個(gè)變量都指向array。這時(shí)候任意一個(gè)引用對array做出的修改都會折射到另一個(gè)引用上。

明白了淺克隆,這里也解釋一下為什么我開始說深淺克隆只針對對象數(shù)組函數(shù)等。先說說棧,棧內(nèi)存有很多優(yōu)點(diǎn),比如讀取速度很快,僅次于寄存器;棧內(nèi)存數(shù)據(jù)可以共享。但也有缺點(diǎn),棧內(nèi)存大小和生存期必須是確定的,缺乏靈活性。而因?yàn)榛咀兞浚╦s的原始值undefined,null,number,string,boolean 類型)一般所占內(nèi)存一半較小且大小固定,所以一般放在棧中,如果放在堆中可能查找耗時(shí)較多。堆內(nèi)存中的數(shù)組、函數(shù)、對象等,一方面可能較大,另一方面不確定大小,所以不能放在棧中,只能在堆里面,由棧內(nèi)存中的句柄(你也可以叫他指針、引用happy jiu ok)加以引用操作。深淺克隆只能針對在堆內(nèi)存中的,有句柄引用的復(fù)雜對象。簡單的直接查就OK啦,沒必要那么那么復(fù)雜。。。

差點(diǎn)跑題,趕緊拉回來。內(nèi)存方面如果想要深入了解可以自行Google,在此不再贅述。

深克隆本質(zhì)上是創(chuàng)造一個(gè)完全一樣的對象,這里簡單介紹兩種js的deepClone方法。talk is cheap show me the code~

一、遞歸完成深克隆

不多說直接上代碼

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)建一個(gè)對象賦給result。然后遍歷arr中所有的元素,遞歸判斷是否是深層對象,不是返回賦給result。這樣就實(shí)現(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í),克隆返回的數(shù)組內(nèi)容不會改變。兩個(gè)數(shù)組是完全不同的兩個(gè)對象,在堆內(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);

最簡單的深克隆,一行代碼搞定,拿好不謝!

臥槽臥槽,內(nèi)心萬馬奔騰有木有?我又是遞歸又是各種判斷for創(chuàng)建對象的,你一行就搞定了?但是事實(shí)上真的一行代碼就OK了~~~(那你上面扯那么多亂七八糟的QAQ)。

好的平復(fù)一下心理落差,來了解一下這個(gè)方法怎么實(shí)現(xiàn)的啊。為了防止長篇大論,我就不具體說json了,自行Google一下。直接說說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文檔的對兩個(gè)方法的介紹,parse方法用于將字符串解析為 JSON,可以任意轉(zhuǎn)換生成的值及其屬性,并返回值。sretingify方法用于從一個(gè)對象中解析出json字符串。

什么意思呢?就是將一個(gè)對象先解析為json對象,然后再解析成object對象。嗯,so easy~~變來變?nèi)ロ樀绖?chuàng)建個(gè)對象完成復(fù)制。

總結(jié)

如一開始說的,原來真的就是這玩意~~~所謂深克隆就是創(chuàng)造一個(gè)完全一樣的對象,將原對象的的所有元素拷貝過來即可。

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

嗯,確實(shí)蠻簡單的嘛哈哈哈??

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

相關(guān)閱讀更多精彩內(nèi)容

  • 什么是深克隆,什么是淺克隆呢? 首先,克隆只針對對象、數(shù)組、函數(shù)等復(fù)雜數(shù)據(jù)。淺克隆就是將棧內(nèi)存中的引用復(fù)制一份,賦...
    七胖子閱讀 582評論 2 1
  • *面試心聲:其實(shí)這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個(gè)offer,總結(jié)起來就是把...
    Dove_iOS閱讀 27,666評論 30 472
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,715評論 19 139
  • 下午去了湘湖,帶了微單,卻忘了帶卡,于是只好手機(jī)拍幾張。光顧著享受了,拍得太少。不過相比西湖的小家碧玉,我更喜歡湘...
    綠妖lianayang閱讀 455評論 4 10
  • ex01簡單print語句 ex02注釋 ex03運(yùn)算符,浮點(diǎn)數(shù) ex04使用變量 ex05格式化字符串 ex06...
    六月之城閱讀 306評論 0 1

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