将函数转换为JSON,然后再次运行

时间:2014-08-03 01:00:20

标签: javascript arrays json function object

我有一个对象数组,每个对象都有一个函数,例如:

var array = [];
var object = {
    param1: 0,
    param2: 0,
    function1: function(){
        param1 += 1;
    },
    function2: function(){
        param2 = new Date().getTime();
    }
}
for(var i=0; i<5; i++){
    array.push(object);
}

然后我想将此数组转换为JSON并保留函数,因此我执行以下操作:

var json = JSON.stringify(array, function(key, val){
    if(typeof(val) === "function"){
        return val.toString();
    }else{
        return val;
    }
});

然后我想让我的对象返回数组,所以我执行以下操作:

var newArray = JSON.parse(json);

但我的问题从这里开始。我在JSON变量中保存的函数被转换为字符串,因此我无法运行它,例如:

alert(newArray[0].param1); //It return 0
newArray[0].function1();  //It says "Uncaught TypeError: string is not a function"
alert(newArray[0].param1); //Do not show anything

我该如何解决这个问题?我该如何运行此功能?我尝试使用eval()而没有成功。我想在没有jQuery或任何插件的情况下解决它。

2 个答案:

答案 0 :(得分:4)

这可能会对您有所帮助:

反序列化函数时,必须使用new Function(arguments, functionBody);对其进行实例化。

例如:

var func = function(a, b) {
    return a * b;
};
var funcStr = func.toString();
// From http://stackoverflow.com/questions/14885995/how-to-get-a-functionss-body-as-string
var funcBody = funcStr.match(/function[^{]+\{([\s\S]*)\}$/)[1];
var newFunc = new Function(['a', 'b'], funcBody);
alert(newFunc(4, 3));

函数是非常复杂的对象(特别是因为可变范围和闭包),所以除非你序列化简单函数,否则这可能会给你带来意想不到的结果。

答案 1 :(得分:0)

您不能调用String,因为String不是Function。 如果你使用eval函数,可能会调用字符串,但似乎不是你想知道的最终答案。

    var object = {
        param1: 0,
        param2: 0,
        function1: "param1 += 1;",
        function2: "param2 = new Date().getTime();"
    };

不幸的是,这段代码存在绑定问题。 因为eval具有不同的背景,所以无法找到params。


Christophe L在上面评论过一个很好的答案。 我认为我们可以清除eval上下文问题,进行一些小编辑。

我们要做的就是将newFunc的上下文作为绑定对象。 您可以在以下代码中看到它

    var array = [];
    var object = {
        param1: 0,
        param2: 0,
        function1: function(){
            this.param1 += 1;
        },
        function2: function(){
            this.param2 = new Date().getTime();
        }
    };
    for(var i=0; i<5; i++){
        array.push(object);
    }

    var json = JSON.stringify(array, function(key, val){
        if(typeof(val) === "function"){
            return val.toString();
        }else{
            return val;
        }
    });

    var newArray = JSON.parse(json);

    var funcStr = newArray[0].function1.toString();
    // From http://stackoverflow.com/questions/14885995/how-to-get-a-functionss-body-as-string
    var funcBody = funcStr.match(/function[^{]+\{([\s\S]*)\}$/)[1];
    var newFunc = new Function('jsonFunc', funcBody);

    newFunc.apply(object);
    console.log(object.param1);