Javascript javascript获取函数体

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3179861/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 03:34:16  来源:igfitidea点击:

javascript get function body

javascriptregex

提问by kalan

I have a function e.g.

我有一个功能,例如

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

How can I get the body of this function?

我怎样才能得到这个函数的主体?

I assume that the only way is to parse the result of test.toString() method, but is there any other way? If parsing is the only way, what will be the regex to get to body? (help with the regex is extremly needed, because I am not familiar with them)

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

回答by polygenelubricants

IF(!!!)you can get the toString(), then you can simply take the substring from the first indexOf("{")to the lastIndexOf("}"). So, something like this "works" (as seen on ideone.com):

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);"

回答by gblazex

2015 update

2015年更新

Upon revisiting the state of function decompilation, it can said that it's generally safe in certain well-considereduse cases and enviroments (e.g: Node.js workers with user defined functions).

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

It should be put in the same bucket as eval, which is a powerful tool that has its place, but should only be used on rare occasions. Think twice, that's my only advice.

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

The conclusions from Kangax's new research:

Kangax 新研究的结论:

  • It's still not standard
  • User-definedfunctions are generally looking sane
  • There are oddball engines(especially when it comes to source code placement, whitespaces, comments, dead code)
  • There might be future oddball engines(particularly mobile or unusual devices with conservative memory/power consumption)
  • Bound functionsdon't show their original source (but do preserve identifier... sometimes)
  • You could run into non-standard extensions(like Mozilla's expression closures)
  • ES6 is coming, and functions can now look very different than they used to
  • Minifiers/preprocessorsare not your friend
  • 还是不标准
  • 用户定义的函数通常看起来很健全
  • 有一些奇怪的引擎(尤其是在源代码放置、空格、注释、死代码方面)
  • 未来可能会有奇怪的引擎(特别是具有保守内存/功耗的移动或不寻常设备)
  • 绑定函数不显示其原始来源(但保留标识符......有时)
  • 您可能会遇到非标准扩展(如 Mozilla 的表达式闭包)
  • ES6 即将到来,功能现在看起来与过去大不相同
  • 压缩器/预处理器不是你的朋友


"function decompilation" — a process of getting string representation of a Function object.

Function decompilation is generally recommended against, as it is a non-standardpart of the language, and as a result, leads to code being non-interoperable and potentially error-prone.

“函数反编译”——获取函数对象的字符串表示的过程。

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

@kangax on comp.lang.javascript

@kangax 在comp.lang.javascript

回答by Domi

Simplest Use-Case

最简单的用例

If you just want to execute the body of the function (e.g. with evalor using the WorkerAPI), you can simply add some code to circumvent all the pitfalls of extracting the body of the function (which, as mentioned by others, is a bad idea in general):

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

'(' + myFunction + ')()';

I am using this trick in this Worker-related JSFiddle.

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

Complete Function Serialization With Accurate Stacktrace

使用准确的 Stacktrace 完成函数序列化

I also wrote a more complete library that can:

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

  1. Serialize any kind of function to string
  2. Be able to send that string representation anywhere else, execute it with any custom arguments, and be able to reproduce the original stacktrace
  1. 将任何类型的函数序列化为字符串
  2. 能够将该字符串表示发送到其他任何地方,使用任何自定义参数执行它,并能够重现原始堆栈跟踪

Check out my CodeBuildercode here.

CodeBuilder在这里查看我的代码

Note that much of the code takes care of making sure that we get an accurate stacktrace, wherever we execute the serialized function at a later point in time.

请注意,大部分代码负责确保我们获得准确的堆栈跟踪,无论我们稍后在何处执行序列化函数。

This fiddledemonstrates a simplified version of that logic:

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

  1. Use JSON.stringifyto properly serialize the function (that comes in handy when, e.g., we want to make it part of a bigger serialization "data package").
  2. We then wrap it in one evalto un-escape the "JSON-ish"-escaped string (JSON does not allow functions + code, so we must use eval), and then in another evalto get back the object we wanted.
  3. We also use //# sourceMappingURL(or the old version //@ sourceMappingURL) to show the right function name in the stacktrace.
  4. You will find that the Stacktrace looks Ok, but it does not give you the correct row and column information relative to the file that we defined the serialized functions in, which is why my Codebuildermakes use of stacktracejsto fix that.
  1. 使用JSON.stringify正确序列化功能(当,例如,我们希望把它更大的系列化“数据包”的一部分就派上用场了)。
  2. 然后我们将它包装在一个中eval以取消转义“JSON-ish”转义字符串(JSON 不允许函数 + 代码,因此我们必须使用eval),然后在另一个中eval以取回我们想要的对象。
  3. 我们还使用//# sourceMappingURL(或旧版本//@ sourceMappingURL)在堆栈跟踪中显示正确的函数名称。
  4. 您会发现 Stacktrace 看起来不错,但它没有为您提供与我们在其中定义序列化函数的文件相关的正确行和列信息,这就是我Codebuilder使用stacktracejs来解决该问题的原因。

I use the CodeBuilderstuff in my (now slightly dated) RPC library where you can find some examples of how it is used:

CodeBuilder在我的(现在有点过时)RPC 库中使用了这些东西,您可以在其中找到一些有关如何使用它的示例:

  1. serializeInlineFunctionexample
  2. serializeFunctionexample
  3. buildFunctionCallexample
  1. serializeInlineFunction例子
  2. serializeFunction例子
  3. buildFunctionCall例子

回答by Ivan Black

extending @polygenelubricants' answer:

扩展@polygenelubricants 的回答

using: .toString()

使用: .toString()

Testee:

受测者:

var y = /* olo{lo} */
    /* {alala} */function/* {ff} */ x/*{s}ls{
}ls*/(/*{*{*/)/* {ha-ha-ha} */
/*

it's a function

*/
{
  return 'x';
// }
}
/*
*/

By indexOfand lastIndexOf:

通过indexOflastIndexOf

function getFunctionBody(fn) {
    function removeCommentsFromSource(str) {
        return str.replace(/(?:\/\*(?:[\s\S]*?)\*\/)|(?:([\s;])+\/\/(?:.*)$)/gm, '');
    }
    var s = removeCommentsFromSource( fn.toString() );
    return s.substring(s.indexOf('{')+1, s.lastIndexOf('}'));
};

getFunctionBody(y);
/*
"
  return 'x' 
"
*/


used: rm comments from js source

使用:来自js源的rm评论

回答by Pat M?chler

This code provides the body when using ES6 arrow functions like var testFn=(q)=>q+1;

此代码在使用 ES6 箭头函数时提供了主体,例如 var testFn=(q)=>q+1;

function getFunctionBody(test){  
    var entire = test.toString(); // note: not safe-guarded; this part may fail like this!
    return entire.substring((entire.indexOf("{")+1)||(entire.indexOf("=>")+2),  entire.lastIndexOf("}")!==-1?entire.lastIndexOf("}"):entire.length);
}

//testing/showcase code
var tests = [
    function () {alert(1);},
    ()=>{return 1;},
    q=>q+1
];

for (var i=0;i<tests.length;i++){
    console.log(tests[i],getFunctionBody(tests[i]));
}

I originally submitted this code as an edit to polygenelubricants accepted answer, but it was rejected as the changes were considered to be too drastic.

我最初提交此代码作为对 polygenelubricants 接受答案的编辑,但由于更改被认为过于剧烈而被拒绝。

回答by Yuchen Huang

you can try this functiion:

你可以试试这个功能:

function extractFunctionBody(fn) {
    var reg = /function \((.*)\)[ ]?{(.*)}$/g;
    var match = reg.exec(fn.toString().replace(/\n/g, ";"));
    if (match){
        return match[2];
    } else {
        return "";
    }
}

回答by Siqueira Junior

var fn1 = function() {};
var fn2 = function() { alert("lol!"); };

Function.prototype.empty = function() {
var x = this.toString().match(/\s*function\s*\w*\s*\(.*?\)\s*{\s*}\s*;?\s*/);
return x != null;
};

alert(fn1.empty()); // true
alert(fn2.empty()); // false

' Solu??o proposta pelo Paulo Torres no grupo A.P.D.A. no facebook.

' Solu??o proposta pelo Paulo Torres 没有组 APDA 没有 facebook。

回答by karlipoppins

Try this:

尝试这个:

/\{(\s*?.*?)*?\}/g.exec(test.toString())[0]

test.toString() will hold your entire declaration.

test.toString() 将保存您的整个声明。

/{(\s*?.?)?}/g will match everything between your braces

/{(\s*?. ?)?}/g 将匹配大括号之间的所有内容