js淺克隆與深克隆

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

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

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

例如:

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

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

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

深克隆本質(zhì)上是創(chuàng)造一個(gè)完全一樣的對(duì)象,這里簡(jiǎn)單介紹兩種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,不是打哪兒來(lái)回哪兒去,然后創(chuàng)建一個(gè)對(duì)象賦給result。然后遍歷arr中所有的元素,遞歸判斷是否是深層對(duì)象,不是返回賦給result。這樣就實(shí)現(xiàn)了深克隆。下面測(cè)試一下:

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"

可以看到在對(duì)原數(shù)組操作時(shí),克隆返回的數(shù)組內(nèi)容不會(huì)改變。兩個(gè)數(shù)組是完全不同的兩個(gè)對(duì)象,在堆內(nèi)存中各占一塊,沒(mé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行稍微改動(dòng)一下:

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文檔的對(duì)兩個(gè)方法的介紹,parse方法用于將字符串解析為 JSON,可以任意轉(zhuǎn)換生成的值及其屬性,并返回值。sretingify方法用于從一個(gè)對(duì)象中解析出json字符串。

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

總結(jié)

所謂深克隆就是創(chuàng)造一個(gè)完全一樣的對(duì)象,將原對(duì)象的的所有元素拷貝過(guò)來(lái)即可。

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

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

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

  • 因?yàn)榻盏捻?xiàng)目需要用到對(duì)數(shù)組做深克隆,所以做一個(gè)簡(jiǎn)要介紹與總結(jié)。 一開(kāi)始聽(tīng)說(shuō)這個(gè)概念的時(shí)候嚇一跳,覺(jué)得高深莫測(cè),有...
    FJW135閱讀 752評(píng)論 0 1
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,506評(píng)論 19 139
  • *面試心聲:其實(shí)這些題本人都沒(méi)怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個(gè)offer,總結(jié)起來(lái)就是把...
    Dove_iOS閱讀 27,580評(píng)論 30 472
  • (酒吧包廂里) “今天怎么進(jìn)來(lái)了?”葉微霞斜靠在沙發(fā)上,打趣地說(shuō)。 “外頭太吵?!?“哦~”葉微霞勾起嘴角“維軒還...
    方木桃景閱讀 186評(píng)論 0 1
  • 注定,他的墳?zāi)褂肋h(yuǎn)是一個(gè)濕潤(rùn)的土丘。 注定,他的墳?zāi)褂肋h(yuǎn)長(zhǎng)不出一朵用于點(diǎn)綴寂寞的野花,哪怕一朵。 我站在幽暗的黃昏...
    寒揚(yáng)閱讀 552評(píng)論 0 37

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