javascript获取功能体

kal*_*lan 26 javascript regex

我有一个功能,例如

var test = function () {alert(1);}
Run Code Online (Sandbox Code Playgroud)

我怎样才能获得这个功能的主体?

我假设唯一的方法是解析test.toString()方法的结果,但还有其他方法吗?如果解析是唯一的方法,那么正则表达式将是什么?(极端需要帮助正则表达式,因为我不熟悉它们)

pol*_*nts 45

IF(!!!)你可以得到toString(),然后你可以简单地从第一个indexOf("{")到子串lastIndexOf("}").所以,像这样的"工作"(如ideone.com上所见):

var test = function () {alert(1);}

var entire = test.toString(); // this part may fail!
var body = entire.substring(entire.indexOf("{") + 1, entire.lastIndexOf("}"));

print(body); // "alert(1);"
Run Code Online (Sandbox Code Playgroud)

  • 从理论上讲,它非常有效.当然,由于含有"{"和"}"的评论,存在大量陷阱.例如:`/**@param {Object} x*/function(x){}` (3认同)
  • 它也会破坏像 `function foo(bar = () => {}) {}` 这样的默认参数。 (2认同)

gbl*_*zex 11

2015年更新

在重新审视函数反编译状态时,可以说它在某些经过深思熟虑的用例和环境中通常是安全的(例如:具有用户定义函数的Node.js worker).

它应该与eval放在同一个桶中,eval是一个功能强大的工具,但它应该只在极少数情况下使用.三思而后行,这是我唯一的建议.

Kangax新研究的结论:

  • 它仍然不标准
  • 用户定义的功能通常看起来很清晰
  • 奇怪的引擎(特别是在源代码放置,空格,注释,死代码时)
  • 可能会有未来的奇怪引擎(特别是具有保守内存/功耗的移动或不寻常设备)
  • 绑定函数不显示其原始源(但有时会保留标识符)
  • 您可能遇到非标准扩展(如Mozilla的表达式闭包)
  • ES6即将推出,功能现在看起来可能与以前完全不同了
  • Minifiers/preprocessors不是你的朋友

"函数反编译" - 获取Function对象的字符串表示的过程.

通常建议使用函数反编译,因为它是 语言的非标准部分,因此导致代码不可互操作且可能 容易出错.

comp.lang.javascript上的 @kangax

  • 那些问SO的人通常不是那些编写教程的人.根据非标准功能**在生产中使用**将导致难以调试的代码,即死亡之吻. (2认同)

Dom*_*omi 6

最简单的用例

如果你只想执行函数的主体(例如使用eval或使用WorkerAPI),你可以简单地添加一些代码来规避提取函数体的所有陷阱(正如其他人所提到的那样,这是个坏主意)一般来说):

'(' + myFunction + ')()';
Run Code Online (Sandbox Code Playgroud)

我在这个Worker相关的JSFiddle中使用这个技巧.

具有精确Stacktrace的完整功能序列化

我还写了一个更完整的库,可以:

  1. 将任何类型的函数序列化为字符串
  2. 能够在其他任何地方发送该字符串表示,使用任何自定义参数执行它,并能够重现原始堆栈跟踪

CodeBuilder在这里查看我的代码.

请注意,大部分代码都会确保我们获得准确的堆栈跟踪,无论我们在以后执行序列化函数的哪个位置.

这个小提琴演示了该逻辑的简化版本:

  1. 使用JSON.stringify正确序列化功能(即派上用场的时候,例如,我们希望把它更大的系列化"数据包"的一部分).
  2. 然后我们将它包装成一个eval以取消转换"JSON-ish"-escaped字符串(JSON不允许函数+代码,所以我们必须使用eval),然后在另一个eval中取回我们想要的对象.
  3. 我们还使用//# sourceMappingURL(或旧版本//@ sourceMappingURL)在stacktrace中显示正确的函数名称.
  4. 您会发现Stacktrace看起来很好,但是它没有提供与我们定义序列化函数的文件相关的正确行和列信息,这就是为什么我Codebuilder使用stacktracejs来修复它.

我使用CodeBuilder我的(现在稍微过时)RPC库中的东西,你可以在其中找到一些如何使用它的例子:

  1. serializeInlineFunction
  2. serializeFunction
  3. buildFunctionCall