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

来源:互联网 发布:小米开源软件 编辑:程序博客网 时间:2024/06/05 18:09

案例官方地址:http://www.rainx.org/2017/01/04/javascript-js%E5%AF%B9%E8%B1%A1%E7%BB%88%E6%9E%81%E5%BA%8F%E5%88%97%E5%8C%96/

你是否遇到了以下问题:

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对象的引用,将形成闭环,会导致序列化失败

更多更牛逼的方案:http://www.rainx.org/

0 0