Javascript中的克隆(拷貝)問題

克履到琛(也就是拷貝)是javascript中很重要也很常見的問題拳昌。克隆就是將一個(gè)對(duì)象里的屬性钠龙、方法等復(fù)制到另一個(gè)對(duì)象中炬藤,且互不影響(即克隆之后,對(duì)一個(gè)對(duì)象進(jìn)行改動(dòng)碴里,不會(huì)影響到另一對(duì)象)沈矿。我們今天就來討論一下原生js中克隆的問題。


action~

現(xiàn)在有一個(gè)對(duì)象

我們現(xiàn)在想把obj里的每一個(gè)屬性拷貝到一個(gè)空對(duì)象var obj1 = {}中咬腋,那么需要寫一個(gè)克隆方法羹膳,首先遍歷一下obj對(duì)象,然后把里面的每一個(gè)屬性都拷貝過去根竿。代碼如下:

在控制臺(tái)中查看obj1陵像,會(huì)發(fā)現(xiàn)實(shí)現(xiàn)了對(duì)obj的拷貝。

我們?cè)賹?duì)這個(gè)方法進(jìn)行一些完善:有可能用戶在執(zhí)行clone方法時(shí)寇壳,只傳origin一個(gè)參數(shù)醒颖,然后將函數(shù)執(zhí)行結(jié)果賦給對(duì)象obj1,所以我們需要在方法最下方加一個(gè)返回值target壳炎,返回克隆結(jié)果图贸,相應(yīng)的也要在函數(shù)體里聲明var target = {}。

還有一種情況obj1對(duì)象里事先有其他屬性,那么函數(shù)體里寫var target = {}顯然是不符合預(yù)期的疏日,所以要完善成var target = target || {};確保萬無一失偿洁。最終該方法完善為:

淺度克隆

下面對(duì)obj進(jìn)行拷貝,且obj1本身有自己的屬性沟优,執(zhí)行代碼如下:

查看一下拷貝結(jié)果

完美拷貝了obj的所有屬性涕滋,又保留了自身屬性。

到這就結(jié)束了么挠阁?要知道js有六大數(shù)據(jù)類型(本文不討論ES6新增的Symbol類型):number宾肺,string,boolean侵俗,undefined锨用,null,object隘谣。

其中number增拥,string,boolean寻歧,undefined掌栅,null歸為原始值一類,而object屬于引用值码泛,具體包括狹義的object猾封,array,function噪珊。

下面往obj對(duì)象里加點(diǎn)引用值晌缘,用我們已經(jīng)寫出來的克隆方法試試:

貌似拷貝成功了

當(dāng)我們對(duì)obj對(duì)象進(jìn)行一波這樣的操作:

再查看obj1會(huì)發(fā)現(xiàn)

在obj1里也多了美容卡和一個(gè)兒子,函數(shù)沒受影響痢站。

我們可以得出這樣的結(jié)論:對(duì)于數(shù)組和對(duì)象枚钓,用上面那種克隆方法是不行的。因?yàn)閷?duì)于數(shù)組和對(duì)象而言瑟押,拷貝的是地址搀捷,他們指向的都是同一個(gè)空間,通過一個(gè)對(duì)象在這個(gè)空間里面加了東西多望,另一個(gè)對(duì)象必然也會(huì)受到影響嫩舟。

而對(duì)于函數(shù)而言,通過上面這種普通的賦值拷貝怀偷,就可以實(shí)現(xiàn)家厌,且互不影響,因?yàn)楹瘮?shù)的克隆會(huì)在內(nèi)存中單獨(dú)開辟一塊空間椎工。

我們管上面寫的這種克隆方法叫淺度克隆饭于,它可應(yīng)用于不包含對(duì)象(狹義的)和數(shù)組的對(duì)象之間的拷貝蜀踏。有點(diǎn)繞哈~




下面我們來解決一下狹義的對(duì)象和數(shù)組的拷貝問題,即我們需要另一種萬全之策——深度克隆掰吕。

先來整理下思路:

1.遍歷待拷貝的對(duì)象果覆;

2.判斷每個(gè)元素是不是原始值,若是殖熟,則通過淺度克隆的手段進(jìn)行拷貝局待;

3.若是引用值,則需要繼續(xù)判斷是對(duì)象還是數(shù)組菱属;

4.再分別建立空數(shù)組或?qū)ο笥脕硎⒎爬锩婕磳⒖截惗鴣淼膶傩灾担?/p>

5.數(shù)組和對(duì)象里面的若是原始值钳榨,則淺拷貝即可實(shí)現(xiàn),若還有引用值纽门,則還需要重復(fù)進(jìn)行上述一系列的判斷薛耻。


上述每一步思路怎么用代碼實(shí)現(xiàn)呢:

1.使用for in進(jìn)行遍歷。但需要注意的是赏陵,for in方法會(huì)把對(duì)象原型里的屬性也一起遍歷了饼齿,所以要與hasOwnProperty()方法進(jìn)行聯(lián)用,hasOwnProperty()方法可以判斷某屬性是不是該對(duì)象自己的屬性瘟滨,從而過濾掉原型中的屬性。

2.用typeof()返回值來進(jìn)行判斷能颁,數(shù)組和對(duì)象的typeof返回值是'object'杂瘸。

3.判斷對(duì)象還是數(shù)組有多種方法,舉出常見的三種:分別是constructor伙菊、instanceof和toString()方法败玉。這里最好用toString()方法,因?yàn)樵谟懈缸佑蛑g拷貝的情況镜硕,constructor和instanceof這兩種是不好用的运翼。

4.就是[]和{}唄。

5.重復(fù)判斷兴枯,自然想到遞歸血淌。

深度克隆方法如下:

深度克隆

注意到origin[prop] !== null這句了么?為啥要加上它财剖,因?yàn)閠ypeof(null)也是'object'悠夯。

來試試吧,我們把obj變得復(fù)雜一點(diǎn)躺坟,給隔壁老王的老婆增加倆兒子:王小寶和王二寶沦补。執(zhí)行過程如下:

看看結(jié)果,沒毛病咪橙。

對(duì)obj的引用值增加一些屬性試試夕膀。

發(fā)現(xiàn)obj1紋絲不動(dòng)虚倒,完美拷貝實(shí)現(xiàn)!




綜上产舞,克隆方法白話完了魂奥,實(shí)戰(zhàn)開發(fā)中針對(duì)實(shí)際需要采取不同的克隆手段。有不足之處歡迎在評(píng)論區(qū)進(jìn)行指正庞瘸,感激不盡~向大神們學(xué)習(xí)捧弃!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市擦囊,隨后出現(xiàn)的幾起案子违霞,更是在濱河造成了極大的恐慌,老刑警劉巖瞬场,帶你破解...
    沈念sama閱讀 221,820評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件买鸽,死亡現(xiàn)場離奇詭異,居然都是意外死亡贯被,警方通過查閱死者的電腦和手機(jī)眼五,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來彤灶,“玉大人看幼,你說我怎么就攤上這事』仙拢” “怎么了诵姜?”我有些...
    開封第一講書人閱讀 168,324評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長搏熄。 經(jīng)常有香客問我棚唆,道長,這世上最難降的妖魔是什么心例? 我笑而不...
    開封第一講書人閱讀 59,714評(píng)論 1 297
  • 正文 為了忘掉前任宵凌,我火速辦了婚禮,結(jié)果婚禮上止后,老公的妹妹穿的比我還像新娘瞎惫。我一直安慰自己,他們只是感情好译株,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,724評(píng)論 6 397
  • 文/花漫 我一把揭開白布微饥。 她就那樣靜靜地躺著,像睡著了一般古戴。 火紅的嫁衣襯著肌膚如雪欠橘。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,328評(píng)論 1 310
  • 那天现恼,我揣著相機(jī)與錄音肃续,去河邊找鬼黍檩。 笑死,一個(gè)胖子當(dāng)著我的面吹牛始锚,可吹牛的內(nèi)容都是我干的刽酱。 我是一名探鬼主播,決...
    沈念sama閱讀 40,897評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼瞧捌,長吁一口氣:“原來是場噩夢啊……” “哼棵里!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起姐呐,我...
    開封第一講書人閱讀 39,804評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤殿怜,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后曙砂,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體头谜,經(jīng)...
    沈念sama閱讀 46,345評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,431評(píng)論 3 340
  • 正文 我和宋清朗相戀三年鸠澈,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了柱告。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,561評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡笑陈,死狀恐怖际度,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情涵妥,我是刑警寧澤乖菱,帶...
    沈念sama閱讀 36,238評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站妹笆,受9級(jí)特大地震影響块请,放射性物質(zhì)發(fā)生泄漏娜氏。R本人自食惡果不足惜拳缠,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,928評(píng)論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望贸弥。 院中可真熱鬧窟坐,春花似錦、人聲如沸绵疲。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽盔憨。三九已至徙菠,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間郁岩,已是汗流浹背婿奔。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評(píng)論 1 272
  • 我被黑心中介騙來泰國打工缺狠, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人萍摊。 一個(gè)月前我還...
    沈念sama閱讀 48,983評(píng)論 3 376
  • 正文 我出身青樓挤茄,卻偏偏與公主長得像,于是被迫代替她去往敵國和親冰木。 傳聞我的和親對(duì)象是個(gè)殘疾皇子穷劈,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,573評(píng)論 2 359

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

  • 1.屬性的簡潔表示法 允許直接寫入變量和函數(shù) 上面代碼表明,ES6 允許在對(duì)象之中踊沸,直接寫變量歇终。這時(shí),屬性名為變量...
    雨飛飛雨閱讀 1,138評(píng)論 0 3
  • 屬性的簡潔表示法 ES6允許直接寫入變量和函數(shù)雕沿,作為對(duì)象的屬性和方法练湿。這樣的書寫更加簡潔。 上面代碼表明审轮,ES6允...
    呼呼哥閱讀 2,925評(píng)論 0 2
  • 第2章 基本語法 2.1 概述 基本句法和變量 語句 JavaScript程序的執(zhí)行單位為行(line)肥哎,也就是一...
    悟名先生閱讀 4,151評(píng)論 0 13
  • 我匆忙穿好衣服鞋襪,臨走的時(shí)候疾渣,眼睛掃了一眼垃圾桶篡诽,空空如也,什么的都沒有榴捡。昨晚我跟曼妮有沒有發(fā)生液體交流呢杈女?有的...
    隔壁村的教主閱讀 1,072評(píng)論 0 1
  • 總是莫名其妙的喜歡翻看一些作者的簡書,看得多了吊圾,自己動(dòng)筆的機(jī)會(huì)卻少了达椰。不知從什么時(shí)候起,我們漸漸不愿意自己動(dòng)手了项乒,...
    大偉5555閱讀 80評(píng)論 0 0