简体   繁体   English

javascript获取功能体

[英]javascript get function body

I have a function eg 我有一个功能,例如

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? 我假设唯一的方法是解析test.toString()方法的结果,但还有其他方法吗? 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) (极端需要帮助正则表达式,因为我不熟悉它们)

IF(!!!) you can get the toString() , then you can simply take the substring from the first indexOf("{") to the lastIndexOf("}") . IF(!!!)你可以得到toString() ,然后你可以简单地从第一个indexOf("{")lastIndexOf("}")获取子串。 So, something like this "works" ( as seen on ideone.com ): 所以,像这样的“工作”( 如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);"

2015 update 2015年更新

Upon revisiting the state of function decompilation , it can said that it's generally safe in certain well-considered use cases and enviroments (eg: Node.js workers with user defined functions). 在重新审视函数反编译状态时,可以说它在某些经过深思熟虑的用例和环境中通常是安全的(例如:具有用户定义函数的Node.js worker)。

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. 它应该与eval放在同一个桶中, eval是一个功能强大的工具,但它应该只在极少数情况下使用。 Think twice, that's my only advice. 三思而后行,这是我唯一的建议。

The conclusions from Kangax's new research : Kangax新研究的结论:

  • It's still not standard 它仍然不标准
  • User-defined functions 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 functions don't show their original source (but do preserve identifier... sometimes) 绑定函数不显示其原始源(但有时会保留标识符)
  • You could run into non-standard extensions (like Mozilla's expression closures) 您可能遇到非标准扩展 (如Mozilla的表达式闭包)
  • ES6 is coming , and functions can now look very different than they used to ES6即将推出 ,功能现在看起来可能与以前完全不同了
  • Minifiers/preprocessors are not your friend Minifiers / preprocessors不是你的朋友

"function decompilation" — a process of getting string representation of a Function object. “函数反编译” - 获取Function对象的字符串表示的过程。

Function decompilation is generally recommended against, as it is a non-standard part of the language, and as a result, leads to code being non-interoperable and potentially error-prone . 通常建议使用函数反编译,因为它是语言的非标准部分,因此导致代码不可互操作且可能容易出错

@kangax on comp.lang.javascript comp.lang.javascript上的 @kangax

Simplest Use-Case 最简单的用例

If you just want to execute the body of the function (eg with eval or using the Worker API), 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或使用Worker API),你可以简单地添加一些代码来规避提取函数体的所有缺陷(正如其他人所提到的那样)一般的坏主意):

'(' + 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 能够在其他任何地方发送该字符串表示,使用任何自定义参数执行它,并能够重现原始堆栈跟踪

Check out my CodeBuilder code 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 fiddle demonstrates a simplified version of that logic: 这个小提琴演示了该逻辑的简化版本:

  1. Use JSON.stringify to properly serialize the function (that comes in handy when, eg, we want to make it part of a bigger serialization "data package"). 使用JSON.stringify来正确地序列化函数(当我们想要使它成为更大的序列化“数据包”的一部分时,它会派上用场)。
  2. We then wrap it in one eval to un-escape the "JSON-ish"-escaped string (JSON does not allow functions + code, so we must use eval ), and then in another eval to get back the object we wanted. 然后我们将它包装在一个eval以取消转换“JSON-ish”-escaped字符串(JSON不允许函数+代码,所以我们必须使用eval ),然后在另一个eval中取回我们想要的对象。
  3. We also use //# sourceMappingURL (or the old version //@ sourceMappingURL ) to show the right function name in the stacktrace. 我们还使用//# sourceMappingURL (或旧版本//@ sourceMappingURL )在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 Codebuilder makes use of stacktracejs to fix that. 您会发现Stacktrace看起来很好,但它没有提供与我们定义序列化函数的文件相关的正确行和列信息,这就是我的Codebuilder使用stacktracejs来修复它的原因。

I use the CodeBuilder stuff in my (now slightly dated) RPC library where you can find some examples of how it is used: 我在我的(现在稍微过时的)RPC库中使用CodeBuilder东西,你可以在其中找到一些如何使用它的例子:

  1. serializeInlineFunction example serializeInlineFunction示例
  2. serializeFunction example serializeFunction示例
  3. buildFunctionCall example buildFunctionCall示例

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 indexOf and lastIndexOf : 通过indexOflastIndexOf

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

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

used: rm comments from js source 使用: 来自js source的rm评论

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 APDA no facebook. 'Soluçãopopostapelo Paulo Torres没有grupo APDA没有facebook。

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接受的答案的编辑,但它被拒绝,因为变化被认为是太激烈。

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

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将匹配大括号之间的所有内容

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM