1. 程式人生 > >Javascript中Json的深拷貝

Javascript中Json的深拷貝

關於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)