如何實現物件的深度克隆

發表於2015-06-15

前端筆試或者面試的時候,很喜歡問的一個問題就是物件的深度克隆,或者說是物件的深度複製。其實這個問題說容易很容易,但是要說全面也挺不易。

要弄明白物件的克隆,首先要明白js中物件的組成。在js中一切例項皆是物件,具體分為原始型別和合成型別。原始型別物件指的是number、string、boolean等,合成型別物件指的是array、object以及function。

又或許你剛聽說“深度克隆”這個詞,簡單來說,就是說有個變數a,a的值是個物件(包括基本資料型別),現在你要建立一個變數b,使得它擁有跟a一樣的方法和屬性等等。但是a和b之間不能相互影響,即a的值的改變不影響b值的變化。

直接賦值可好?

實踐證明某些JavaScript的原始資料型別,如果要克隆直接賦值即可。

關於function的深度複製:查閱了一些資料,function的深度複製似乎和原始資料型別的深度複製一樣。

本來我也是這麼認為的,直到文章下出現了評論。思考後我覺得function和普通的物件一樣,只是我們在平常應用中習慣了整體的重新賦值,導致它在深度複製中的表現和原始型別一致:

於是乎對於function型別的深度克隆,直接賦值似乎並不應該是一種最好的方法(儘管實際應用中足矣)。那麼如何克隆?可以參考文章下面的評論,不失為一種解決方案。

但是物件呢?

顯然與預期不符,為什麼會這樣?因為原始資料型別儲存的是物件的實際資料,而物件型別儲存的是物件的引用地址。上面的例子呢也就是說a和b物件引用了同一個地址,無論改變a還是改變b,其實根本操作是一樣的,都是對那塊空間地址中的值的改變。

於是我們知道了,對於基本的物件來說,不能只能用=賦值,思索後寫下如下程式碼:

似乎可以解決一般的物件(包括Array)的深度克隆了,或許這兒會有疑問,new String(..)這類的也是物件啊,可是這樣寫你克隆不了啊…但是樓主覺得深度克隆的考點不在這裡,可能在於:

  1. 原始資料型別的直接賦值
  2. function的exception
  3. 物件的深度克隆中Array型別的判斷
  4. 克隆函式的遞迴呼叫

相關文章