最近想全職當碼農,面試時候被問到了深拷貝,我噼裏啪啦說了一通,感覺很牛逼,問我自己寫過沒有,我說沒有,但是我可以寫。其實我很心虛,估計現場寫會卡殼。。。。。
思路
- 深拷貝需要迭代拷貝對象的所有屬性,如果屬性是引用型:Object,則繼續遞歸迭代。
實現
-
首先可以寫一個殼子函數,包裹一個將要反覆遞歸調用自身的函數。
function deepCopy(obj) { const handleDeepCopy = obj=>{ const clonedObj = obj instanceof Array? []:{} return clonedObj } return handleDeepCopy(obj) }
clonedObj就是即將克隆返回的新對象
今後會這麼使用它:let newobj = deepCopy(oldobj)
newobj就是經過深拷貝的新對象,這樣在操作newobj的時候就不會對oldobj產生干擾了 -
接着完善遞歸拷貝邏輯。
- 用for in迭代數組和對象的屬性。(若不用forin迭代,用foreach代碼會比較多,數組和對象的處理方式會有所不同)
- 判斷屬性的類型,是否是引用型。
- 如果是引用型,將clonedObj對應的property賦值爲handleDeepCopy(obj[property])【遞歸拷貝】。
-
如果不是引用型,直接將clonedObj對應的property賦值爲obj[property]。
function deepCopy(obj) { const handleDeepCopy = obj=>{ const clonedObj = obj instanceof Array? []:{} // add for in logic here for (let keyOrIndex in obj) { if(obj[keyOrIndex] instanceof Object) { clonedObj[keyOrIndex] = handleDeepCopy(obj[keyOrIndex]) } else { clonedObj[keyOrIndex] = obj[keyOrIndex] } } // for in logic over return clonedObj } return handleDeepCopy(obj) }
- 以上邏輯還有疏忽的地方,沒有在開始時判斷傳進的obj究竟是不是一個引用型,如果不是,就應該直接將obj返回。另外在for in中需要使用hasOwnProperty進行判斷,因爲我們只想拷貝obj自身的屬性。爲了節約篇幅,增加以上邏輯後修改的代碼在:stackblitz