我希望能够检查给定的函数是否为空。也就是说,它的主体中没有任何东西,例如:
function foo() {}
function iAmEmpty(a) {
// yep, empty
}通过使用toString()和一些正则表达式,通过一些最初的尝试,我已经得到了一些我认为可能行得通的东西。
function foo(a, b, c) {}
/^function[^{]+\{\s*\}/m.test(foo.toString()); // true
function bar(a, b, c) { var d; }
/^function[^{]+\{\s*\}/m.test(bar.toString()); // false我只是想知道有没有更好的方法?你能看到上面有什么问题吗?
发布于 2010-12-03 22:11:17
这是不可取的。没有标准来确定函数的toString()方法应该返回什么,所以即使您在当前的浏览器中运行此方法,未来的浏览器也可能合理地更改其实现并破坏您的代码。
Kangax曾写过一篇简短的文章:http://perfectionkills.com/those-tricky-functions/
发布于 2017-08-04 04:50:23
箭头函数...
我相信你已经知道,javascript支持arrow functions,它非常简洁,但不幸的是,它不能与你整洁的regex一起工作。
我很快将漂亮的regex转换成了它自己的function,它接受一个function作为输入,并返回它是否为空以便于以后使用。为了演示箭头函数是如何被广泛使用的,我将其放在其中:
isEmpty = f => /^function[^{]+\{\s*\}/m.test(f.toString())现在,我们可以很容易地测试一个空函数:
function eF() {}正如我们对isEmpty(eF)所期望的那样,它返回true。
再一次使用实际的函数:
function retOne() {return 1;}同样,与预期的isEmpty(retOne)一样,它返回false。
然而,我遇到的问题是箭头函数,所以为了再次初始化一个空的,我们有一个原始的更短的语法:
eF = () => {}它的'stringified'版本与之前的版本有很大的不同:
"() => {}"当然,在本例中,当我们需要true时,调用isEmpty(eF)返回false。我不确定你是否需要测试所有函数(例如,包括arrow functions)是否都是空的,但如果你这样做了,你的regex将需要修改……
我自己并不擅长编写它们,但是我已经尝试过几次,而且还有一件事需要考虑,那就是arrow functions的宽松性质,特别是documentation的这一部分
(param1, param2, …, paramN) => { statements }
(param1, param2, …, paramN) => expression
// equivalent to: (param1, param2, …, paramN) => { return expression; }
// Parentheses are optional when there's only one parameter name:
(singleParam) => { statements }
singleParam => { statements }这说明了花括号{...}并不总是必需的。所以这个函数:
retOne = () => 1是valid,可能会使形成一个新的regex更加困难。我想到的一个解决方法是使用以下命令从f.toString()中删除所有的花括号:
str.replace(/[{}]/g, '')。
然后在那里使用regex test。
如果您希望arrow functions也能够进行测试,希望这是一些有用的考虑因素。
发布于 2017-08-04 03:07:58
您可以尝试的最好方法(因为这很难实现)是添加acorn或esprima (使用箭头函数too)库并处理JavaScript函数。它会将其标记化,让你解析,这样你就可以根据你的喜好来处理它,检查里面是否真的有零代码,或者只有变量声明而没有任何计算和返回,等等。
实现起来相当简单:
function check(f) {
console.log("");
console.log("Checking", f);
var syntax = esprima.parse(f);
if (syntax.body.length != 1) {
console.log("Weird process");
} else {
function processBody(body) {
if (!body || body.length == 0) {
console.log("Body seems empty. YAY!");
} else {
for (var i = 0, command; command = body[i]; i++) {
if (command.type != "VariableDeclaration") {
console.log("Body has a", command.type, ", so is not empty.");
return;
}
}
console.log("Body has only variable declarations, so is empty! (or not, whatever fit your needs)");
}
}
function process(dec) {
if (dec.type != "FunctionDeclaration") {
console.log("Weird declaration");
} else {
console.log("Function", dec.id.name, "has", dec.params.length, "params");
processBody(dec.body.body);
}
}
process(syntax.body[0]);
}
}
check("function hasReturn(arg1, arg2) {var a = arg1 + arg2;return a;}");
check("function hasArgumentsButNoBody(arg1, arg2) {}");
check("function isCompletelyEmptyWithSpacesAndTabsAndLinefeeds() { \t \t \r\n \r\n }");
check("function hasOnlyVariables() {var a, b = 2; var c = 1 + b;}");<script src="https://cdnjs.cloudflare.com/ajax/libs/esprima/2.7.3/esprima.min.js"></script>
这不会运行函数,只是解析它们,所以使用非安全函数运行是安全的。
https://stackoverflow.com/questions/4346186
复制相似问题