我正在编写一些用于编写用户编写的JavaScript函数的代码,并且在逻辑中遇到了一个问题,如果所讨论的函数永远不会返回值{{1,那么我想触发特定行为永远不会评估关键字。
目前我假设如果一个函数返回return
,它还没有返回,但是这不是严格正确的 - 因为函数总是undefined
,或者返回一个值未定义的属性。
通过函数调用,您可以始终知道由于return undefined
属性使用了多少参数,我想知道是否有人知道函数返回值的类似技巧?
那么,是否可以区分arguments.length
,a
或甚至b
c
答案 0 :(得分:4)
不,您无法可靠,跨浏览,通过仅使用return
没有值或使用return undefined
来判断函数是否仅通过其代码末尾返回。这由规范的Section 13.2.1涵盖。
这里的另一个答案表明你可以通过分析函数的源代码来实现它。但是,没有标准的机制可以做到这一点。虽然几乎所有的浏览器都可以从Function#toString
中获得某种形式的源代码,但有些代码却没有(主要是移动浏览器),并且它没有被规范定义。但是如果你有一组你支持的浏览器,并且它们都拥有它,那将是你唯一真正的选择 - 但即使这样,你也不一定知道在函数中采用了哪个代码分支。
答案 1 :(得分:2)
将函数留空也将返回undefined,因此a,b和c都将返回相同的值。
实现这样的事情的唯一方法是在函数本身中实际设置某种标志,但我猜你希望能够独立于实际函数的实现来做这个。
答案 2 :(得分:2)
没有办法区分。
如果您真的想要,可以尝试分析函数的源代码并确定它是否有任何return语句,如果没有,则假设它不会返回值。当然,这有点难以确定函数是否有时返回而其他函数没有(例如,if-block中的return语句)
答案 3 :(得分:2)
这很疯狂,绝对不推荐,它会创建一个函数副本,修改函数体并使用eval
function returnProxy(func,args) {
var returnFlag = Math.random()+"";
// create new function based on passed function body
var fullFuncBody = func.toString();
var tmpFuncStr = "function "+ fullFuncBody.substr(fullFuncBody.indexOf("("));
tmpFuncStr = tmpFuncStr.substr(0,tmpFuncStr.length-1)+"\nreturn '"+returnFlag+"'}";
var tmpFunc;
eval("tmpFunc = "+tmpFuncStr); // really bad things
var funcOut = tmpFunc.apply(this,args);
return {
out: (funcOut == returnFlag) ? undefined : funcOut,
returned: (returnFlag != funcOut)
}
}
假设你有这样的功能,
function someFunction(action) {
switch(action) {
case 1:
return undefined;
case 2:
return "hello";
}
}
你可以使用这样的代理功能:
returnProxy(someFunction,[1]); // instead of calling someFunction(1)
第一个参数是函数本身,第二个参数是参数数组
返回值将是一个具有2个属性的对象,out
包含函数结果,returned
是一个布尔值,表示函数是否返回
示例输出,
returnProxy(someFunction,[1]); // {out: undefined, returned: true}
returnProxy(someFunction,[2]); // {out: "hello", returned: true}
returnProxy(someFunction,[3]); // {out: undefined, returned: false}
答案 4 :(得分:0)
您只能通过包装器调用函数,但我不确定这是否适合您的用例。
function invoker(f) {
var actualFunc = f,
invokeCount = 0;
function invoke() {
invokeCount = invokeCount +1;
return actualFunc.apply(this, arguments);
}
function invoked() {
return invokeCount;
}
return {
invoke: invoke,
invoked: invoked
};
}
var a = function(){ };
var b = function(){ return undefined; };
var c = function(){ if(1){}else{return undefined;}; };
var ainvoker = new invoker(a);
alert(ainvoker.invoke());
alert(ainvoker.invoked());