我有一个功能,例如
var test = function () {alert(1);}
如何获得此功能的主体?
我假设唯一的方法是解析test.toString()方法的结果,但还有其他方法吗?如果解析是唯一的方法,那么正则表达式将是什么? (极端需要帮助正则表达式,因为我不熟悉它们)
答案 0 :(得分:43)
IF(!!!) 您可以获取toString()
,然后您可以简单地将第一个indexOf("{")
的子字符串带到lastIndexOf("}")
。所以,这样的“工作”(as seen on 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);"
答案 1 :(得分:10)
2015年更新
在重新访问函数反编译的状态后,可以说它在某些考虑周全的用例和环境中通常是安全的(例如:Node.js worker with users定义的功能)。
它应与 eval 放在同一个存储桶中,这是一个功能强大的工具,但它应该只在极少数情况下使用。 三思而后行,这是我唯一的建议。
上的@kangax“函数反编译” - 获取的过程 Function对象的字符串表示形式。
函数反编译通常是 建议反对,因为它是 非标准部分语言,以及 结果,导致代码存在 不可互操作且可能 的易错强>
答案 2 :(得分:6)
如果你只想执行函数体(例如使用eval
或使用Worker
API),你可以简单地添加一些代码来规避提取体的所有缺陷。功能(正如其他人所说,一般来说是一个坏主意):
'(' + myFunction + ')()';
我在this Worker
-related JSFiddle中使用此技巧。
我还写了一个更完整的库,可以:
Check out my CodeBuilder
code here
请注意,大部分代码都会确保我们获得准确的堆栈跟踪,无论我们在以后执行序列化函数的哪个位置。
This fiddle演示了该逻辑的简化版本:
JSON.stringify
正确序列化该功能(例如,当我们想让它成为更大的序列化“数据包”的一部分时,它会派上用场。)eval
中以取消转义“JSON-ish”-escaped字符串(JSON不允许函数+代码,因此我们必须使用eval
),然后在另一个eval
来取回我们想要的对象。//# sourceMappingURL
(或旧版本//@ sourceMappingURL
)在堆栈跟踪中显示正确的函数名称。Codebuilder
使用{{{ 3}}来解决这个问题。我在我的(现在稍微陈旧的)RPC库中使用CodeBuilder
内容,您可以在其中找到一些如何使用它的示例:
答案 3 :(得分:3)
扩展@polygenelubricants'answer:
使用:.toString()
<强>测试对象:强>
var y = /* olo{lo} */
/* {alala} */function/* {ff} */ x/*{s}ls{
}ls*/(/*{*{*/)/* {ha-ha-ha} */
/*
it's a function
*/
{
return 'x';
// }
}
/*
*/
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'
"
*/
答案 4 :(得分:0)
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çãopopostapelo Paulo Torres no grupo A.P.D.A.没有facebook。
答案 5 :(得分:0)
此代码在使用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]));
}
我最初提交此代码作为polygenelubricants接受答案的编辑,但它被拒绝,因为这些更改被认为过于激烈。
答案 6 :(得分:0)
您可以尝试以下功能:
function extractFunctionBody(fn) {
var reg = /function \((.*)\)[ ]?{(.*)}$/g;
var match = reg.exec(fn.toString().replace(/\n/g, ";"));
if (match){
return match[2];
} else {
return "";
}
}
答案 7 :(得分:-1)
试试这个:
/\{(\s*?.*?)*?\}/g.exec(test.toString())[0]
test.toString()将保留您的整个声明。
/ {(\ s *?。?)?} / g将匹配大括号之间的所有内容