javascript如何用遞迴寫一個簡單的樹形結構示例
阿新 • • 發佈:2019-02-17
var jsonToArray=function (nodes) { var r=[]; if (Array.isArray(nodes)) { for (var i=0, l=nodes.length; i<l; i++) { r.push(nodes[i]); if (Array.isArray(nodes[i]["children"])&&nodes[i]["children"].length>0) //將children遞迴的push到最外層的陣列r裡面 r = r.concat(jsonToArray(nodes[i]["children"])); delete nodes[i]["children"] } } return r; }
這樣,不管後臺返回什麼格式給我們,我們都可以自由的互轉了,不管是帶層級的轉不帶層級的,還是把不帶層級的轉化為帶有層級的,都只需要呼叫一個函式就可以輕鬆解決。
不過這裡有一個隱患,就是由於物件的引用關係,操作後雖然返回了我們需要東西,但是會改變原來的資料。
為了不影響到原來的資料,我們需要複製一份資料,需要進行一次深拷貝。
為什麼是深拷貝而不是淺拷貝?因為淺拷貝只會複製最外面的一層,假入某一個key值裡面又是一個物件,那對複製後的物件的這個key的值進行操作通用會影響到原來的物件。淺拷貝的方法有很多,ES6的assign,jq第一個引數不為true的 $.extend(),陣列的slice(0),還有很多很多。
對於標準的json格式的物件,可以用JSON.parse(JSON.stringify(obj))來實現。當然,本文寫的是遞迴,所以還是來手寫一個
function deepCopy(obj){ var object; if(Object.prototype.toString.call(obj)=="[object Array]"){ object=[]; for(var i=0;i<obj.length;i++){ object.push(deepCopy(obj[i])) } return object } if(Object.prototype.toString.call(obj)=="[object Object]"){ object={}; for(var p in obj){ object[p]=obj[p] } return object } }
其實有點類似於淺拷貝,淺拷貝會複製一層,那麼我們判斷某個值是物件,通過遞迴再來一次(好比飲料中獎再來一瓶一樣,如果中獎了,就遞迴再來一瓶,又中獎就又遞迴再來一瓶,直到不再中獎),也就是說我們通過無盡的淺拷貝來達到複製一個完全的新的物件的效果。
這樣,對樹結構操作時,只需要傳入深拷貝後新物件,就不會影響原來的物件了;
jsonToArray(deepCopy(data));
或者是arrayToJson(deepCopy(data)):