Javascript中Json的深拷貝
阿新 • • 發佈:2019-01-03
關於Json的深拷貝,雖然網上的達人們各抒己見,但都不是很合我意,比如我要複製的json為如下程式碼--一個子級包含父級,同級子級包含同級子級的複雜結構。對於這樣的一個結構來說,複製就會把這些相應物件的原型抹掉或者出現遞迴無限迴圈等問題。
var ak = { name: "名字", test: null, key: { id: { id1: "33", id2: "334", id3: [{ key: "1", arr: ["3", "2", true], arr2: { 1: 1, 2: 2, 3: 3, } }, "2", "3"] }, Card: "2321323", }, id: 1, is: false, k33: [1, 2, [1, 2]], un: ak, func: function () { } } ak["prent"] = ak; ak.k33[0] = { key: ak.key.id };
以前較為簡單粗暴的就是 JSON.parse(JSON.stringify(obj)),但是這樣複製不了function和會在包含母級原型的子級下出問題。
所以我自己寫了一個方法:
var CopyJson = function (json) { //同型元素 var ptList = new Array(); //找出各類元素(元素,路徑,尋找歷史) var allPath = new Array(); function _getAllKeyType(Obj, Key, Path, LogList) { //新增尋找歷史 if (!Key) Key = "$"; if (!Path) Path = "$" if (!LogList) LogList = new Array(); LogList.push({ Key: Key, Obj: Obj, Path: Path }); for (var key in Obj) { var keyPath = Path + "." + key //判斷是否包含key if (!Obj.hasOwnProperty(key)) continue; if (typeof Obj[key] === 'object' && Obj[key] != null) { //判斷是否是 var FindParentObj = LogList.find(p=>Object.is(p.Obj, Obj[key])); //如果是新增並跳出 if (FindParentObj != null) { ptList.push({ Path: keyPath, Parent: FindParentObj.Path, Key: key, ParentKey: FindParentObj.Key }); continue; } allPath.push(keyPath) _getAllKeyType(Obj[key], key, keyPath, LogList); } } } _getAllKeyType(json) //尋找同級元素 function _copyjson(p, c, Jpath) { if (!Jpath) Jpath = "$"; var c = c || {}; for (var i in p) { if (!p.hasOwnProperty(i)) { continue; } if (typeof p[i] === 'object') { var kypath = Jpath + "." + i; if (ptList.find(q=>q.Path == kypath) != null) continue; switch ((Object.prototype.toString.call(p[i])).toLowerCase().split(" ")[1].replace("]", "")) { case "array": c[i] = []; break; case "object": c[i] = {}; break; case "null": c[i] = null; break; default: break; } //不是同型元素 _copyjson(p[i], c[i], kypath); } else { c[i] = p[i]; } } return c; } var newcpyjson = _copyjson(json); function _jsonpath(obj, findpath) { findpath.split(".").forEach(p=> { if (typeof (obj) != "undefined" && p != "$" && obj != null) { obj = obj[p]; } }) return obj; } while (ptList.length > 0) { var p = ptList.shift() if (p.Parent != "$" && allPath.find(fq=>fq == p.Parent) == null) { ptList.push(p); } else { var ptObj = _jsonpath(newcpyjson, p.Parent); // console.log(JSON.stringify(p)) // console.log(ptObj) var _pathlist = p.Path.split(".") _pathlist.pop(); var sonObj = _jsonpath(newcpyjson, _pathlist.join(".")) sonObj[p.Key] = ptObj allPath.push(p.Path); } } return newcpyjson }
呼叫方案 var copyobj = CopyJson(ak)