Javascript 如何确定函数是否为空
我希望能够检查给定函数是否为空。也就是说,它的身体里没有任何东西,例如:Javascript 如何确定函数是否为空,javascript,reflection,Javascript,Reflection,我希望能够检查给定函数是否为空。也就是说,它的身体里没有任何东西,例如: 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 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
我只是想知道是否有更好的方法?您可以看到上面的内容有什么问题吗?这是不可取的。没有标准可以精确地确定函数的
toString()
方法应该返回什么,因此,即使您在当前的浏览器中实现了这一点,未来的浏览器也可能有理由更改其实现并破坏您的代码
Kangax对此做了简要的描述:我不认为这有什么用处,但是您可以通过将模式锚定到字符串的端来简化它
/[^{\s]\s*\}$/.test(String(bar))
您可以尝试的最好方法是添加或(也使用箭头函数)库,并处理JavaScript函数,以适应最大的可能性(因为这很难实现)。它将标记化它以供您解析,因此您可以根据自己的喜好对其进行处理,检查内部是否实际上没有代码,或者是否只有没有任何计算或返回的变量声明,等等 实现起来非常简单:
功能检查(f){
控制台日志(“”);
控制台日志(“检查”,f);
var syntax=esprima.parse(f);
if(syntax.body.length!=1){
日志(“奇怪的过程”);
}否则{
函数processBody(body){
如果(!body | | body.length==0){
log(“身体似乎是空的,耶!”);
}否则{
for(var i=0,command;command=body[i];i++){
if(command.type!=“VariableDeclaration”){
log(“Body有一个”,command.type,”,所以不是空的。”);
返回;
}
}
log(“Body只有变量声明,所以是空的!(或者不是,只要适合您的需要)”;
}
}
功能过程(dec){
if(dec.type!=“函数声明”){
console.log(“怪异声明”);
}否则{
log(“函数”,dec.id.name,“has”,dec.params.length,“params”);
进程体(dec.body.body);
}
}
进程(syntax.body[0]);
}
}
检查(“函数hasrurn(arg1,arg2){var a=arg1+arg2;返回a;}”);
检查(“函数hasArgumentsButNoBody(arg1,arg2){}”);
检查(“函数完全为空,带有空格和tabsandlinefeeds(){\t\t\r\n\r\n}”);
检查(“函数hasOnlyVariables(){var a,b=2;var c=1+b;}”)代码>
箭头函数。。。
我相信您一定知道,javascript
支持非常简洁的代码,但不幸的是,它不能与您的整洁的regex
配合使用
我很快将您的niceregex
转换为自己的函数
,它将函数
作为输入,并返回它是否为空,以方便以后使用。为了演示如何广泛使用箭头函数,我将其放在一个示例中:
isEmpty = f => /^function[^{]+\{\s*\}/m.test(f.toString())
现在,我们可以轻松地测试一个空函数:
function eF() {}
function retOne() {return 1;}
retOne = () => 1
正如我们所期望的那样,isEmpty(eF)
返回true
还有一个实际的功能:
function eF() {}
function retOne() {return 1;}
retOne = () => 1
与预期的一样,isEmpty(retOne)
返回false
但是,我遇到的问题是箭头函数,因此要再次初始化空函数,我们使用了较短的原始语法:
eF = () => {}
它的“stringified”
版本与之前的版本有很大不同:
"() => {}"
当然,在这种情况下,调用isEmpty(eF)
会在需要true
时返回false
。我不确定您是否需要测试所有函数(即,包括箭头函数
)是否为空,但如果需要,您的正则表达式
将需要修改
<>我自己写的不是很好,但是已经尝试了一对又一件事情,你可能要考虑的是<代码>箭头函数< /代码>的宽泛性。
这说明了花括号{…}
并非总是必要的。所以这个函数:
function eF() {}
function retOne() {return 1;}
retOne = () => 1
是有效的
,并且可能使生成新的正则表达式变得更加困难。我想到的一个解决方法是使用以下方法删除f.toString()
中的所有花括号:
str.replace(/[{}]/g',)
然后在那里使用regex测试
希望这是一个有帮助的事情,如果你想让代码>箭头函数< /代码>也能被测试。 < P>它很简单,只需检查函数中包含的函数,然后检查它是否是空的。
检查此项
以下是完整的工作代码:
function foo(a, b, c) {}
function bar(a, b, c) {
var d;
}
function isEmpty(value) {
return (value == null || value.length === 0);
}
function check(test) {
var entire = test.toString();
var body = entire.slice(entire.indexOf("{") + 1, entire.lastIndexOf("}"));
return body;
}
console.log(isEmpty(check(foo)), isEmpty(check(bar))); //return true false
JS反射的概念让我很开心,但是关于这个问题;您已经处理了空格和多行,所以afaik这是最好的。不要忘记查找所有注释的方法体(如果这是您的规范),我认为这样做是一个好方法。@Brad,注释会自动从toString()的输出中删除,afaik。重复:谢谢链接!我没有意识到浏览器实现的差异如此之大。@Tim ES5:ES6@ManasJayanth:关键词是“精确”。这两个规范都说返回了函数的“依赖于实现的表示”。哦,对了。我的坏:)但在Mac上运行几个简单的函数toString
s似乎可以在不同浏览器(FF、Safari和Chrome)上返回一致的结果,即非本机函数。如果该函数重写toString方法,则此操作无效。@AlexisTyler检查plunker@AlexisTyler在你的问题中提到了重写,如果你想重写它,你可以将默认的toString函数保存在另一个函数中