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

0x001前言

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


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

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



0x002淺度克隆

? ? ? ? 淺度克隆,也是最簡單的克隆,同時也是缺陷最明顯的克隆方案,我們先來看一個最簡單的淺度克隆(又叫:淺克?。┌咐?/p>


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

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


原型失配

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


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


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

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

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


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


遞歸死循環(huán)

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

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


深度限制

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


成功克隆有環(huán)

0x005接力棒克隆

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

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


測試后效果

0x006總結(jié)

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

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

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

  • 這是16年5月份編輯的一份比較雜亂適合自己觀看的學(xué)習(xí)記錄文檔,今天18年5月份再次想寫文章,發(fā)現(xiàn)簡書還為我保存起的...
    Jenaral閱讀 3,115評論 2 9
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對...
    cosWriter閱讀 11,618評論 1 32
  • 第3章 基本概念 3.1 語法 3.2 關(guān)鍵字和保留字 3.3 變量 3.4 數(shù)據(jù)類型 5種簡單數(shù)據(jù)類型:Unde...
    RickCole閱讀 5,488評論 0 21
  • 印象非常深刻,和小夏見面的那天,外面烏云密布,突然一陣瓢潑大雨襲來,小夏就是在這樣的大暴雨中走進了我們約定的地方-...
    生涯P姐閱讀 574評論 0 5
  • 這段時間越來越愛看書了。每次看完一本書,再在一堆新書里面選出下一本要看的書的時候,那份莫名的期盼與渴望讓...
    運啟閱讀 212評論 0 3

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