【JS】克隆索烹,怎樣才能完美?

0x001前言

?????????在前端中弱睦,我們都知道百姓,數(shù)組和對象是引用傳遞,正是因?yàn)檫@一特性是存在况木,讓我們又喜又憂垒拢。喜:喜在我們可以將結(jié)構(gòu)復(fù)雜的數(shù)據(jù)進(jìn)行拆解修改旬迹。憂:憂在數(shù)據(jù)復(fù)制的時(shí)候,擺脫耦合性和相關(guān)度是很麻煩的求类。為此奔垦,我們需要人為的增加一些方法,去復(fù)制引用類型的數(shù)據(jù)尸疆,在這里椿猎,我們優(yōu)雅的稱這種復(fù)制的手段叫做:克隆(clone)寿弱。


復(fù)雜數(shù)據(jù)拆解賦值犯眠,同時(shí)也體現(xiàn)出引用類型的耦合性和相關(guān)性

? ? ? ? 寫一個(gè)克隆函數(shù),幾乎是所有前端學(xué)習(xí)者的必經(jīng)之路症革,我們現(xiàn)在來好好討論一下筐咧,你,曾經(jīng)寫過的克隆噪矛,都有什么問題量蕊,到底,有沒有一個(gè)完美的克隆方案艇挨?讀者別急残炮,我們慢慢往下看。



0x002淺度克隆

? ? ? ? 淺度克隆雷袋,也是最簡單的克隆吉殃,同時(shí)也是缺陷最明顯的克隆方案,我們先來看一個(gè)最簡單的淺度克驴(又叫:淺克碌吧住)案例:


淺克隆函數(shù)版本一

? ? ? ? 我們可以看出,這個(gè)版本的淺克隆方案就是把要克隆的數(shù)據(jù)遍歷一遍鸠删,然后賦值抱完,返回,這樣寫確實(shí)可以避免一定相關(guān)性刃泡,但是如果數(shù)據(jù)里面依然是引用類型呢巧娱?那不就失效了嗎,因?yàn)闇\克隆只克隆了第一層(我們稱為原始層)烘贴。其次禁添,這個(gè)clone函數(shù)只能克隆數(shù)組和原始對象,對于構(gòu)造函數(shù)構(gòu)造出的對象桨踪,克隆結(jié)果會(huì)變成原始對象老翘,數(shù)據(jù)就不是一種類型了,這也是我們不想要的,這個(gè)問題我們暫時(shí)稱它:原型失配問題


原型失配

? ? ? ? 從這個(gè)例子我們可以清晰的看出克隆出來的b和之前的a完全不是一個(gè)數(shù)據(jù)種類铺峭,那么能否解決它呢墓怀?或者該如何解決呢?我們可以嘗試使用虛擬構(gòu)造來得出一個(gè)同類型的數(shù)據(jù)體卫键,然后再正常的一一克隆傀履,如下圖所示:


虛擬構(gòu)造的淺克隆


? ? ? ? 細(xì)心的朋友應(yīng)該發(fā)現(xiàn)了,雖然構(gòu)造后大體都很相似了莉炉,但是控制臺(tái)的類型標(biāo)注還是明顯區(qū)分出了Foo和F钓账,這個(gè)問題,還真沒有太好的方法去解決呢袱,但是官扣,對于數(shù)據(jù)體達(dá)到一樣后,我們可以近似的認(rèn)為他們是同類型構(gòu)造體羞福,而且再他們的construct中惕蹄,也是相同的函數(shù)。至此治专,淺克隆基本上完成卖陵,接下來就要解決淺克隆的不能深層次的克隆問題。

0x003深度克隆和它的嚴(yán)重問題

? ? ? ? 解決淺克隆不能深層克隆最簡單的方式就是遍歷遞進(jìn)式的克隆张峰,也就是深度克隆泪蔫,說白了,深度克隆就是淺克隆的自我遞歸喘批,所有當(dāng)我們有一個(gè)現(xiàn)成的淺克隆撩荣,只需要對此稍加修改,就能得到普遍的深度克隆函數(shù)饶深。


? ? ? ? 可以看見餐曹,深度克隆就是在淺度克隆基礎(chǔ)上進(jìn)行了遞歸,只要判斷出是引用類型敌厘,就遞歸克隆台猴,這樣就完全消除了相關(guān)性和耦合性。到此俱两,很多人都覺得已經(jīng)沒有問題了饱狂,也可以自信的發(fā)個(gè)朋友圈炫耀下代碼了,仔細(xì)想想宪彩,看看我標(biāo)注的黑體休讳,仔細(xì)推敲一下?你會(huì)發(fā)現(xiàn)尿孔,它衍腥,其實(shí)隱藏著一個(gè)巨大的bug磺樱,就是:死循環(huán)(也叫遞歸沒有結(jié)束點(diǎn))。


遞歸死循環(huán)

0x004深度限制法去解決死循環(huán)問題

? ? ? ? ? ? ? ? 這個(gè)問題的產(chǎn)生婆咸,主要是對象源于有環(huán)對象,他們的路徑交叉后芜辕,成為環(huán)狀尚骄,為了讓我們的克隆能夠完美,就要去避免死循環(huán)侵续,第一種方法:深度限制法倔丈,就是限制最多克隆多深,我們假設(shè)再復(fù)雜的數(shù)據(jù)状蜗,對于前端而言需五,也超不出10層深度,那么我們?nèi)藶橄拗扑淖畲笊疃葹?0轧坎,當(dāng)超出后結(jié)束遞歸宏邮。顯而易見,這個(gè)方法缺點(diǎn)很明顯缸血,就是當(dāng)數(shù)據(jù)深度超過10層蜜氨,就失效了,當(dāng)然你可以讓它更深捎泻,使用場景就是你能確定你克隆數(shù)據(jù)最大深度飒炎。有點(diǎn)在于簡單,只需要對前面的深度克隆加一個(gè)深度限制就可以笆豁。


深度限制

? ? ? ? 可以看見郎汪,函數(shù)中多了一個(gè)depth參數(shù),它闯狱,就是控制深度的變量煞赢,我們默認(rèn)10,你可以讓他更大扩氢。


成功克隆有環(huán)

0x005接力棒克隆

? ? ? ? 有些人耕驰,喜歡追求更完美的事物,我也一樣录豺,我不喜歡人工的方法調(diào)節(jié)它的克隆方式朦肘,我也不想知道數(shù)據(jù)深度有多深,但是双饥,我就想成功克隆有環(huán)這種惡心人的數(shù)據(jù)媒抠,為此,我嘗試了一個(gè)最笨的方法咏花,筆者給他起名叫做:接力棒克隆趴生。

? ? ? ? [由于代碼過長阀趴,我傳到的我的github,歡迎copy測試苍匆,有問題請告訴我]https://github.com/antilmid/CloneJS/blob/master/relayBarClone.js


測試后效果

0x006總結(jié)

? ? ? ? 每個(gè)人的思考方式不一樣刘急,解決一件事情的方法就會(huì)不一樣,上面的多種方法都為筆者所寫浸踩,但我相信叔汁,還有更多優(yōu)秀的寫法,也歡迎在評論總結(jié)检碗,從頭到尾据块,筆者總結(jié)的克隆中的種種問題,每個(gè)克隆都不是完美的折剃,至于什么克隆最好用另假,完全取決于你的數(shù)據(jù)環(huán)境。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末怕犁,一起剝皮案震驚了整個(gè)濱河市边篮,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌因苹,老刑警劉巖苟耻,帶你破解...
    沈念sama閱讀 222,590評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異扶檐,居然都是意外死亡凶杖,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評論 3 399
  • 文/潘曉璐 我一進(jìn)店門款筑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來智蝠,“玉大人,你說我怎么就攤上這事奈梳¤就澹” “怎么了?”我有些...
    開封第一講書人閱讀 169,301評論 0 362
  • 文/不壞的土叔 我叫張陵攘须,是天一觀的道長漆撞。 經(jīng)常有香客問我,道長于宙,這世上最難降的妖魔是什么浮驳? 我笑而不...
    開封第一講書人閱讀 60,078評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮捞魁,結(jié)果婚禮上至会,老公的妹妹穿的比我還像新娘。我一直安慰自己谱俭,他們只是感情好奉件,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,082評論 6 398
  • 文/花漫 我一把揭開白布宵蛀。 她就那樣靜靜地躺著,像睡著了一般县貌。 火紅的嫁衣襯著肌膚如雪术陶。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,682評論 1 312
  • 那天煤痕,我揣著相機(jī)與錄音瞳别,去河邊找鬼。 笑死杭攻,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的疤坝。 我是一名探鬼主播兆解,決...
    沈念sama閱讀 41,155評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼跑揉!你這毒婦竟也來了锅睛?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,098評論 0 277
  • 序言:老撾萬榮一對情侶失蹤历谍,失蹤者是張志新(化名)和其女友劉穎现拒,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體望侈,經(jīng)...
    沈念sama閱讀 46,638評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡印蔬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,701評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了脱衙。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片侥猬。...
    茶點(diǎn)故事閱讀 40,852評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖捐韩,靈堂內(nèi)的尸體忽然破棺而出退唠,到底是詐尸還是另有隱情,我是刑警寧澤荤胁,帶...
    沈念sama閱讀 36,520評論 5 351
  • 正文 年R本政府宣布瞧预,位于F島的核電站,受9級特大地震影響仅政,放射性物質(zhì)發(fā)生泄漏垢油。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,181評論 3 335
  • 文/蒙蒙 一已旧、第九天 我趴在偏房一處隱蔽的房頂上張望秸苗。 院中可真熱鬧,春花似錦运褪、人聲如沸惊楼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽檀咙。三九已至雅倒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間弧可,已是汗流浹背蔑匣。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留棕诵,地道東北人裁良。 一個(gè)月前我還...
    沈念sama閱讀 49,279評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像校套,于是被迫代替她去往敵國和親价脾。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,851評論 2 361

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