【问题标题】:Inverse operation for Javascript's Function.toString()Javascript 的 Function.toString() 的逆运算
【发布时间】:2011-12-08 13:44:59
【问题描述】:

对于 Javascript 应用程序,我需要能够让用户保存对象的状态。这涉及保存一组以前动态或通过 GUI 创建的自定义函数,并在以后加载这些存储的函数。本质上我需要序列化和反序列化函数。

现在我通过使用 Function 对象的 .toString() 方法来实现序列化部分:

func.toString().replace('"', '\"').replace(/(\r)/g, ' ').replace(/(\n)/g, ' ').replace(/(\t)/g, ' ')

这给了我像这样美丽的“序列化”函数(注意该函数未命名):

"function (someParameter) {this.someFunctionName(return 'something';}"

反序列化这是我挣扎的地方。我目前反序列化函数的最佳解决方案是:

var func = eval( 't =' +  so.actions[i].func);

请注意我在调用eval() 之前如何在序列化函数前面加上t =。我不喜欢这样做,因为它会创建一个全局变量,但我找不到解决方法。如果不添加此内容,我会收到“SyntaxError: Unexpected token (”。添加 var t = 时,eval() 不会返回函数,而是返回 undefined

是否有其他方法可以“反序列化”未命名的函数?

PS:我知道在用户输入上使用 eval() 的安全隐患。在可预见的未来,我是这个软件的唯一用户,所以目前这不是问题。

【问题讨论】:

    标签: javascript


    【解决方案1】:

    您可以使用 Function 构造函数来避免创建全局变量:

    var func = Function("return " + so.actions[i].func)();
    

    这相当于:

    var func = eval("(function () { return " + so.actions[i].func + " })()");
    

    需要注意的一点是周围的闭包您将无法捕获,因此当您进行序列化和反序列化时,函数内部的变量会“改变”。

    编辑

    我没有想,你当然可以这样做:

    var func = eval("(" + so.actions[i].func + ")");
    

    【讨论】:

    • 关闭已处理。这些函数只能使用Function.call(theContextTheFunctionIsExecutedIn) 执行。除了你建议用括号括起来的序列化函数之外 - 你知道为什么吗?
    • 根据MDN,添加括号会将其从函数声明更改为函数表达式。 (它是括号中表达式的一部分。)由于它是一个表达式,它会返回一个值,您可以将其分配给func。这也可能取决于 eval 当前所在的范围。
    【解决方案2】:

    这应该有效:

    eval('var func = ' + so.actions[i].func);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-08-03
      • 1970-01-01
      • 1970-01-01
      • 2020-02-09
      • 2011-05-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多