深拷貝與淺拷貝的實(shí)現(xiàn)(一)

最近的學(xué)習(xí)中期丰,仔細(xì)研究了下深拷貝和淺拷貝,下面就來(lái)簡(jiǎn)單的總結(jié)下漠嵌。

數(shù)據(jù)類(lèi)型

首先我們了解下兩種數(shù)據(jù)類(lèi)型

1咐汞、基本類(lèi)型:像Number、String儒鹿、Boolean等這種為基本類(lèi)型

2化撕、復(fù)雜類(lèi)型:Object和Array

淺拷貝與深拷貝的概念

接著我們分別來(lái)了解下淺拷貝和深拷貝,深拷貝和淺拷貝是只針對(duì)Object和Array這樣的復(fù)雜類(lèi)型的约炎。

淺拷貝

var a = {

????myname: 'yana'

};

var b = a;

b.myname = '小雅';

console.log(b.myname);????// 小雅

console.log(a.myname);????// 小雅



var a = ['myname', 'yana'];

var b = a;

b[1] = '小雅';

console.log(a);????// ["myname", "小雅"]

console.log(b);????// ["myname", "小雅"]


可以看出植阴,對(duì)于對(duì)象或數(shù)組類(lèi)型,當(dāng)我們將a賦值給b圾浅,然后更改b中的屬性掠手,a也會(huì)隨著變化。

也就是說(shuō)a和b指向了同一塊內(nèi)存狸捕,所以修改其中任意的值喷鸽,另一個(gè)值都會(huì)隨之變化,這就是淺拷貝灸拍。

深拷貝

剛剛我們了解了什么是淺拷貝做祝,那么相應(yīng)的,如果給b放到新的內(nèi)存中鸡岗,將a的各個(gè)屬性都復(fù)制到新內(nèi)存里混槐,就是深拷貝。

也就是說(shuō)轩性,當(dāng)b中的屬性有變化的時(shí)候声登,a內(nèi)的屬性不會(huì)發(fā)生變化。

淺拷貝

那么除了上面簡(jiǎn)單的賦值引用,還有哪些方法使用了淺拷貝呢悯嗓?

Object.assign()

在MDN上介紹Object.assign():”O(jiān)bject.assign() 方法用于將所有可枚舉的屬性的值從一個(gè)或多個(gè)源對(duì)象復(fù)制到目標(biāo)對(duì)象件舵。它將返回目標(biāo)對(duì)象「”

復(fù)制一個(gè)對(duì)象

var target = {a: 1, b: 1};

var copy1 = {a: 2, b: 2, c: {ca: 21, cb: 22, cc: 23}};

var copy2 = {c: {ca: 31, cb: 32, cd: 34}};

var result = Object.assign(target, copy1, copy2);

console.log(target);????// {a: 2, b: 2, c: {ca: 31, cb: 32, cc: 33}}

console.log(target === result);????// true


可以看到芦圾,Object.assign()拷貝的只是屬性值,假如源對(duì)象的屬性值是一個(gè)指向?qū)ο蟮囊枚砣希仓豢截惸莻€(gè)引用值个少。所以O(shè)bject.assign()只能用于淺拷貝或是合并對(duì)象。這是Object.assign()值得注意的地方眯杏。

深拷貝

那么下面我們就來(lái)說(shuō)說(shuō)復(fù)雜的深拷貝夜焦。

jQuery.extend()

說(shuō)到深拷貝,第一想到的就是jQuery.extend()方法岂贩,下面我們簡(jiǎn)單看下jQuery.extend()的使用茫经。

jQuery.extend( [deep ], target, object1 [, objectN ] ),其中deep為Boolean類(lèi)型萎津,如果是true卸伞,則進(jìn)行深拷貝。

我們還是用上面的數(shù)據(jù)來(lái)看下extend()方法锉屈。

var target = {a: 1, b: 1};

var copy1 = {a: 2, b: 2, c: {ca: 21, cb: 22, cc: 23}};

var copy2 = {c: {ca: 31, cb: 32, cd: 34}};

var result = $.extend(true, target, copy1, copy2);?? // 進(jìn)行深拷貝

console.log(target);????// {a: 2, b: 2, c: {ca: 31, cb: 32, cc: 23, cd: 34}}


var target = {a: 1, b: 1};

var copy1 = {a: 2, b: 2, c: {ca: 21, cb: 22, cc: 23}};

var copy2 = {c: {ca: 31, cb: 32, cd: 34}};

var result = $.extend(target, copy1, copy2);?? // 不進(jìn)行深拷貝

console.log(target);????// {a: 1, b: 1, c: {ca: 31, cb: 32, cd:34}}


通過(guò)上面的對(duì)比可以看出荤傲,當(dāng)使用extend()進(jìn)行深拷貝的時(shí)候,對(duì)象的所有屬性都添加到target中了颈渊。

我們知道了extend()可以進(jìn)行深拷貝遂黍,那么extend()是如何實(shí)現(xiàn)深拷貝的呢体箕?

先來(lái)看下jQuery.extend()源碼

jQuery.extend = jQuery.fn.extend = function() {

????var options, name, src, copy, copyIsArray, clone,

????????target = arguments[ 0 ] || {},

????????i = 1,

????????length = arguments.length,

????????deep = false;


????// Handle a deep copy situation

????if ( typeof target === "boolean" ) {

????????deep = target;


????????// Skip the boolean and the target

????????target = arguments[ i ] || {};

????????i++;

????}


????// Handle case when target is a string or something (possible in deep copy)

????if ( typeof target !== "object" && !jQuery.isFunction( target ) ) {

????????target = {};

????}


????// Extend jQuery itself if only one argument is passed

????if ( i === length ) {

????????target = this;

????????i--;

????}


????for ( ; i < length; i++ ) {


????????// Only deal with non-null/undefined values

????????if ( ( options = arguments[ i ] ) != null ) {


????????????// Extend the base object

????????????for ( name in options ) {

????????????????src = target[ name ];

????????????????copy = options[ name ];


????????????????// Prevent never-ending loop

????????????????if ( target === copy ) {

????????????????????continue;

????????????????}


????????????????// Recurse if we're merging plain objects or arrays

????????????????if ( deep && copy && ( jQuery.isPlainObject( copy ) || ( copyIsArray = Array.isArray( copy ) ) ) ) {


????????????????????if ( copyIsArray ) {

????????????????????????copyIsArray = false;

????????????????????????clone = src && Array.isArray( src ) ? src : [];


????????????????????} else {

????????????????????????clone = src && jQuery.isPlainObject( src ) ? src : {};

????????????????????}


????????????????????// Never move original objects, clone them

????????????????????target[ name ] = jQuery.extend( deep, clone, copy );


????????????????// Don't bring in undefined values

????????????????} else if ( copy !== undefined ) {

????????????????????target[ name ] = copy;

????????????????}

????????????}

????????}

????}

????// Return the modified object

????return target;

};

主要看下關(guān)于深拷貝的部分脚作,取第一個(gè)參數(shù)测萎,如果是boolean類(lèi)型的丙者,就賦值給deep,下面如果deep為true(也就是進(jìn)行深拷貝)摩骨,就遞歸調(diào)用extend()奏赘,這樣就將對(duì)象的所有屬性都添加到了target中實(shí)現(xiàn)了深拷貝胡野。

JSON.parse()和JSON.stringify()

上面的jQuery源碼是否讓你眼花繚亂竹揍?有沒(méi)有什么辦法無(wú)腦實(shí)現(xiàn)深拷貝呢敬飒?JSON.parse()和JSON.stringify()給了我們一個(gè)基本的解決辦法。

var target = {a: 1, b: 1, c: {ca: 11, cb: 12, cc: 13}};

var targetCopy = JSON.parse(JSON.stringify(target));

targetCopy.a = 2;

targetCopy.c.ca = 21;

console.log(target);?? // {a: 1, b: 1, c: {ca: 11, cb: 12, cc: 13}}

console.log(targetCopy);????// {a: 2, b: 1, c: {ca: 21, cb: 12, cc: 13}}

console.log(target === targetCopy);??// false


可以看到改變targetCopy并沒(méi)有改變?cè)嫉膖arget鬼佣,繼承的屬性也沒(méi)有丟失驶拱,因此實(shí)現(xiàn)了基本的深拷貝霜浴。

但是用JSON.parse()和JSON.stringify()會(huì)有一個(gè)問(wèn)題晶衷。

JSON.parse()和JSON.stringify()能正確處理的對(duì)象只有Number、String、Array等能夠被json表示的數(shù)據(jù)結(jié)構(gòu)晌纫,因此函數(shù)這種不能被json表示的類(lèi)型將不能被正確處理税迷。

var target = {

????a: 1,

????b: 2,

????hello: function() {

????????????console.log("Hello, world!");

????}

};

var copy = JSON.parse(JSON.stringify(target));

console.log(copy);?? // {a: 1, b: 2}


上面的例子可以看出,hello這個(gè)屬性由于是函數(shù)類(lèi)型锹漱,使用JSON.parse()和JSON.stringify()后丟失了箭养。

因此JSON.parse()和JSON.stringify()還是需要謹(jǐn)慎使用。

下篇文章我會(huì)繼續(xù)為大家說(shuō)明深拷貝的各種實(shí)現(xiàn)哥牍。

未完待續(xù)……

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末毕泌,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子嗅辣,更是在濱河造成了極大的恐慌撼泛,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,682評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件澡谭,死亡現(xiàn)場(chǎng)離奇詭異愿题,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)蛙奖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)潘酗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人雁仲,你說(shuō)我怎么就攤上這事仔夺。” “怎么了攒砖?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,083評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵囚灼,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我祭衩,道長(zhǎng)灶体,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,763評(píng)論 1 295
  • 正文 為了忘掉前任掐暮,我火速辦了婚禮蝎抽,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘路克。我一直安慰自己樟结,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布精算。 她就那樣靜靜地躺著瓢宦,像睡著了一般。 火紅的嫁衣襯著肌膚如雪灰羽。 梳的紋絲不亂的頭發(fā)上驮履,一...
    開(kāi)封第一講書(shū)人閱讀 51,624評(píng)論 1 305
  • 那天鱼辙,我揣著相機(jī)與錄音,去河邊找鬼玫镐。 笑死倒戏,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的恐似。 我是一名探鬼主播杜跷,決...
    沈念sama閱讀 40,358評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼矫夷!你這毒婦竟也來(lái)了葛闷?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,261評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤双藕,失蹤者是張志新(化名)和其女友劉穎孵运,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體蔓彩,經(jīng)...
    沈念sama閱讀 45,722評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡治笨,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了赤嚼。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片旷赖。...
    茶點(diǎn)故事閱讀 40,030評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖更卒,靈堂內(nèi)的尸體忽然破棺而出等孵,到底是詐尸還是另有隱情,我是刑警寧澤蹂空,帶...
    沈念sama閱讀 35,737評(píng)論 5 346
  • 正文 年R本政府宣布俯萌,位于F島的核電站,受9級(jí)特大地震影響上枕,放射性物質(zhì)發(fā)生泄漏咐熙。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評(píng)論 3 330
  • 文/蒙蒙 一辨萍、第九天 我趴在偏房一處隱蔽的房頂上張望棋恼。 院中可真熱鬧,春花似錦锈玉、人聲如沸爪飘。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,941評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)师崎。三九已至,卻和暖如春椅棺,著一層夾襖步出監(jiān)牢的瞬間犁罩,已是汗流浹背齐蔽。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,057評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留昼汗,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,237評(píng)論 3 371
  • 正文 我出身青樓鬼雀,卻偏偏與公主長(zhǎng)得像顷窒,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子源哩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評(píng)論 2 355

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