JavaScript之js对象终极序列化(可序列化函数)

你是否遇到了以下问题:

js对象A中包含几个对象B。并且A,B对象根据需求后期动态添加的函数比如(B.show=function(){…})

你用JSON.stringify()原生序列化只能序列化对象的属性,方法是不能够被序列化的

比如下边的案例:

function A(){
    this.name="A";
    this.arr=new Array();
    this.put=function(para){
        this.arr[this.arr.length]=para;
    }
}
function B(){
    this.name="B";
    this.show="";
}

var a = new A();

var b1=new B();
b1.show=function(){
    alert("function 1");
}

var b2=new B();
b2.show=function(){
    alert("function 2");
}

a.put(b);
a.put(b2);
console.log(JSON.stringify(a));

最后输出的结果是

{"name":"A","arr":[{"name":"B"},{"name":"B"}]}

那么你动态给b1,b2绑定的show方法就不会被序列化,使用这个json字符串还原a对象的时候就不能被准确的还原

本人在网上查找大量资料,知乎,stackoverflow总结出此序列化方案:

function serialize(obj, name){
    var result = "";
    function serializeInternal(o, path) {
        for (p in o) {
            var value = o[p];
            if (typeof value != "object") {
                if (typeof value == "string") {
                    result += "\n" + path + "[" + (isNaN(p)?"\""+p+"\"":p) + "] = " + "\"" + value.replace(/\"/g,"\\\"") + "\""+";";
                }else {
                    result += "\n" + path + "[" + (isNaN(p)?"\""+p+"\"":p) + "] = " + value+";";
                }
            }
            else {
                if (value instanceof Array) {
                    result += "\n" + path +"[" + (isNaN(p)?"\""+p+"\"":p) + "]"+"="+"new Array();";
                    serializeInternal(value, path + "[" + (isNaN(p)?"\""+p+"\"":p) + "]");
                } else {
                    result += "\n" + path  + "[" + (isNaN(p)?"\""+p+"\"":p) + "]"+"="+"new Object();";
                    serializeInternal(value, path +"[" + (isNaN(p)?"\""+p+"\"":p) + "]");
                }
            }
        }
    }
    serializeInternal(obj, name);
    return result;
}

使用上边的序列化方法再次序列化案例:

function A(){
    this.name="A";
    this.arr=new Array();
    this.put=function(para){
        this.arr[this.arr.length]=para;
    }
}
function B(){
    this.name="B";
    this.show="";
}

var a = new A();

var b=new B();
b.show=function(){
    alert("function 1");
}

var b2=new B();
b2.show=function(){
    alert("function 2");
}

a.put(b);
a.put(b2);
console.log(serialize(a,"a"));

以上方式将输出生成a对象所有的js语句:

a["name"] = "A";
a["arr"]=new Array();
a["arr"][0]=new Object();
a["arr"][0]["name"] = "B";
a["arr"][0]["show"] = function (){
alert("function 1");
};
a["arr"][1]=new Object();
a["arr"][1]["name"] = "B";
a["arr"][1]["show"] = function (){
alert("function 2");
};
a["put"] = function (para){
this.arr[this.arr.length]=para;
};

通过eval方法执行以上的语句就可以完整的还原a对象:
案例:

var deserialization_lang= serialize(a,"a");//deserialization_lang生成的语句
var a=new Object();
eval(deserialization_lang);
a.arr[0].show();//成功的弹出function 1

可见,此方法不仅能够完整的还原出a对象,还能还原出a对象arr数组里边的b对象。

注意:在使用过程中,如果b对象持有a对象的引用,将形成闭环,会导致序列化失败

发表评论