javascript的淺復(fù)制和深復(fù)制

????javascript的基本類型包括字符串强法、數(shù)字万俗、布爾、數(shù)組饮怯、對象闰歪、Null、Undefined硕淑】慰ⅲ基本類型和對象最大的不同在于他們的傳值方式:基本類型是按值傳遞的嘉赎,但是對象是按引用傳值的.
基本類型:

var a = 1;
var b = a;
b = 2;
console.log(a);  //1
console.log(b); //2

從上面的例子可以看出置媳,由于是按值傳遞,所以改變b的值不會(huì)改變a
如果是對象公条,由于是按引用傳值拇囊,類似的做法會(huì)改變另外一個(gè)相關(guān)對象的屬性,這就是淺復(fù)制(新舊對象公用一塊內(nèi)存空間):

var obj1 = { a:1 , b:2 };
var obj2 = obj1;
obj.a = 3;
console.log(obj1);  //{ a:3 , b:2 }
console.log(obj2);  //{ a:3 , b:2 }
console.log(obj1 === obj2); //true

如果不讓原本obj1對象屬性靶橱,那么就是深復(fù)制(新舊對象使用不同內(nèi)存空間)
簡單實(shí)現(xiàn):

var obj2 = { a:obj1.a , b:obj1.b };
obj2.a = 3;
console.log(obj1);  //{ a:1 , b:2 }
console.log(obj2);  //{ a:3 , b:2 }
console.log(obj1 === obj2); //false

這種方法可以實(shí)現(xiàn)深度復(fù)制寥袭,但是略顯臃腫,而且如果有嵌套對象(有多層對象)實(shí)現(xiàn)起來就更麻煩了关霸,比如:

var obj1 = { grade : { math : 100 , Chinese : 90 } };
var obj2 = { grade : obj1.grade };
obj2.grade.math = 120;
console.log(obj1);  // { grade : { math : 120 , Chinese : 90 } };  
var obj2 = { grade : obj1.grade.math , grade : obj1.grade.Chinese }; //這樣才能深度復(fù)制

深度復(fù)制除了上面方法传黄,還可以用其他方法實(shí)現(xiàn)

1.ES6的Object.assign

ES6引入了一個(gè)Object.assign的新函數(shù),可以把任意個(gè)源對象自身的可枚舉屬性拷貝給目標(biāo)對象队寇,然后再返回目標(biāo)對象膘掰。不過其進(jìn)行的是淺復(fù)制i,復(fù)制的是對象屬性的引用
不過佳遣,它還是可以實(shí)現(xiàn)一層的深度復(fù)制识埋,比起前面的手動(dòng)復(fù)制要簡單一點(diǎn),比如

var obj1 = { a:1 , b:2 };
var obj2 = Object.assign( {} , obj1 };
obj.a = 3;
console.log(obj1);  //{ a:1 , b:2 }
console.log(obj2);  //{ a:3 , b:2 }

2.JSON.stringify+JSON.parse

前面提到了零渐,js的基本類型是按值傳遞的窒舟,那么既然有這樣的特性我們完全可以將對象轉(zhuǎn)換成字符串,然后再用parse解析成新對象

var obj1 = { a:1 , b:2 };
var obj2 = JSON.parse(JSON.stringify(obj1));
obj.a = 3;
console.log(obj1);  //{ a:1 , b:2 }
console.log(obj2);  //{ a:3 , b:2 }
console.log(obj1 === obj2); //false

不過诵盼,這個(gè)方法還是有缺陷惠豺,只有可以轉(zhuǎn)換成JSON格式的對象才可以使用,RegExp對象是無法通過該方法實(shí)現(xiàn)深度復(fù)制的风宁,函數(shù)也無法使用

3.遞歸拷貝

function deepClone(initalObj,finalObj){
    var obj = finalObj || {};
    for(var i  in initalObj){
        var prop = initalObj[i];
        if(prop === obj)
          continue;
        if(typeof prop === 'object'){
            obj[i] = (prop.constructor === Array) ? [] : {};
            arguments.callee(prop,obj[i]);
        }else{
            obj[i] = prop;
        }
    }
    return obj;
}

4.Object.create(initalObj)

注意和前面遞歸方法的區(qū)別

function deepClone(initalObj,finalObj){
    var obj = finalObj || {};
    for(var i  in initalObj){
        var prop = initalObj[i];
        if(prop === obj)
          continue;
        if(typeof prop === 'object'){
            obj[i] = (prop.constructor === Array) ? [] : Object.create(prop);
            arguments.callee(prop,obj[i]);
        }else{
            obj[i] = prop;
        }
    }
    return obj;
}

5.slice和concat巧妙的方法

實(shí)質(zhì)上這也是淺復(fù)制耕腾,只不過返回一個(gè)淺復(fù)制了原數(shù)組中的元素的一個(gè)新數(shù)組

var arr1 = [1, 2, 3, 4],
    arr2 = arr1.slice(0),
    arr3 = arr1.concat();
 
console.log(arr1, arr2, arr3);
arr2[2] = 10;
arr3[2] = 11;
console.log(arr1[2], arr2[2], arr3[2]);
> 1,2,3,4, 1,2,3,4, 1,2,3,4
> 3, 10, 11

console.log( arr1 === arr2 ); //false
console.log( arr1 === arr3 ); //false

又比如:

var array = [1, [1,2,3], {name:"array"}]; 
var array_concat = array.concat();
var array_slice = array.slice(0);
array_concat[1][0] = 5;  //改變array_concat中數(shù)組元素的值 
console.log(array[1]); //[5,2,3] 
console.log(array_slice[1]); //[5,2,3] 
array_slice[2].name = "array_slice"; //改變array_slice中對象元素的值 
console.log(array[2].name); //array_slice
console.log(array_concat[2].name); //array_slice

jQuery提供了一個(gè)$.extend方法可以做深度復(fù)制

var arr1 = [1, 2, [3, 4], {a: 5, b: 6}, 7],
    arr2 = $.extend(true, [], arr1);
console.log(arr1, arr2);
arr2[1] = 10;
console.log(arr1, arr2);

還有一個(gè)叫l(wèi)odash的函數(shù)庫的_.cloneDeep方法可以實(shí)現(xiàn)深度復(fù)制

參考:http://www.cnblogs.com/Chen-XiaoJun/p/6217373.html
http://web.jobbole.com/88602/
https://github.com/wengjq/Blog/issues/3

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市杀糯,隨后出現(xiàn)的幾起案子扫俺,更是在濱河造成了極大的恐慌,老刑警劉巖固翰,帶你破解...
    沈念sama閱讀 218,036評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件狼纬,死亡現(xiàn)場離奇詭異羹呵,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)疗琉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門冈欢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人盈简,你說我怎么就攤上這事凑耻。” “怎么了柠贤?”我有些...
    開封第一講書人閱讀 164,411評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵香浩,是天一觀的道長。 經(jīng)常有香客問我臼勉,道長邻吭,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,622評(píng)論 1 293
  • 正文 為了忘掉前任宴霸,我火速辦了婚禮囱晴,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘瓢谢。我一直安慰自己畸写,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,661評(píng)論 6 392
  • 文/花漫 我一把揭開白布氓扛。 她就那樣靜靜地躺著枯芬,像睡著了一般。 火紅的嫁衣襯著肌膚如雪幢尚。 梳的紋絲不亂的頭發(fā)上破停,一...
    開封第一講書人閱讀 51,521評(píng)論 1 304
  • 那天,我揣著相機(jī)與錄音尉剩,去河邊找鬼真慢。 笑死,一個(gè)胖子當(dāng)著我的面吹牛理茎,可吹牛的內(nèi)容都是我干的黑界。 我是一名探鬼主播,決...
    沈念sama閱讀 40,288評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼皂林,長吁一口氣:“原來是場噩夢啊……” “哼朗鸠!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起础倍,我...
    開封第一講書人閱讀 39,200評(píng)論 0 276
  • 序言:老撾萬榮一對情侶失蹤烛占,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體忆家,經(jīng)...
    沈念sama閱讀 45,644評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡犹菇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,837評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了芽卿。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片揭芍。...
    茶點(diǎn)故事閱讀 39,953評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖卸例,靈堂內(nèi)的尸體忽然破棺而出称杨,到底是詐尸還是另有隱情,我是刑警寧澤筷转,帶...
    沈念sama閱讀 35,673評(píng)論 5 346
  • 正文 年R本政府宣布姑原,位于F島的核電站,受9級(jí)特大地震影響旦装,放射性物質(zhì)發(fā)生泄漏页衙。R本人自食惡果不足惜摊滔,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,281評(píng)論 3 329
  • 文/蒙蒙 一混坞、第九天 我趴在偏房一處隱蔽的房頂上張望季率。 院中可真熱鬧,春花似錦、人聲如沸喘漏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,889評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽牌废。三九已至,卻和暖如春页响,著一層夾襖步出監(jiān)牢的瞬間篓足,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,011評(píng)論 1 269
  • 我被黑心中介騙來泰國打工闰蚕, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留栈拖,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,119評(píng)論 3 370
  • 正文 我出身青樓没陡,卻偏偏與公主長得像涩哟,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子盼玄,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,901評(píng)論 2 355

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

  • 國家電網(wǎng)公司企業(yè)標(biāo)準(zhǔn)(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報(bào)批稿:20170802 前言: 排版 ...
    庭說閱讀 10,970評(píng)論 6 13
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理贴彼,服務(wù)發(fā)現(xiàn),斷路器埃儿,智...
    卡卡羅2017閱讀 134,657評(píng)論 18 139
  • 作者:D2and2D (一) 她躲在樹后面器仗, 看起來就像一件衣服 掛在樹上 如果你細(xì)心觀察 就會(huì)發(fā)現(xiàn)無數(shù)的線索都指...
    D2and2D閱讀 347評(píng)論 0 0
  • 文學(xué)從來沒有任何捷徑,訪道終南終是死路一條童番。思考得久了精钮,才能淌出血與淚來暴心。但世界從不乏探索者,他們有大的魄力杂拨,大的...
    鐵匠文學(xué)閱讀 316評(píng)論 0 1
  • 顏丙翔閱讀 173評(píng)論 0 0