有没有办法判断javascript函数是否已返回?
我目前正在编写一些代码来包装用户编写的JavaScript函数,并且在逻辑中遇到了一个点,如果所讨论的函数从未返回值,即从未计算过有没有办法判断javascript函数是否已返回?,javascript,function,return,return-value,undefined,Javascript,Function,Return,Return Value,Undefined,我目前正在编写一些代码来包装用户编写的JavaScript函数,并且在逻辑中遇到了一个点,如果所讨论的函数从未返回值,即从未计算过return关键字,我希望触发一个特定的行为 目前,我假设如果函数返回undefined,它就没有返回,但是这并不是严格正确的,因为函数总是可以返回undefined,或者返回未定义属性的值 通过函数调用,您总是可以知道由于arguments.length属性使用了多少参数,我想知道是否有人知道函数返回值的类似技巧 那么,是否可以区分a、b甚至c的返回值之间的差异 v
return
关键字,我希望触发一个特定的行为
目前,我假设如果函数返回undefined
,它就没有返回,但是这并不是严格正确的,因为函数总是可以返回undefined
,或者返回未定义属性的值
通过函数调用,您总是可以知道由于arguments.length
属性使用了多少参数,我想知道是否有人知道函数返回值的类似技巧
那么,是否可以区分a
、b
甚至c
的返回值之间的差异
var a = function(){ };
var b = function(){ return undefined; };
var c = function(){ if(1){}else{return undefined;}; };
将函数留空也将返回未定义的值,因此a、b和c都将返回相同的值
实现这类功能的唯一方法是在函数本身中设置某种标志,但我猜您希望能够独立于实际函数的实现来实现这一点。无法区分这两者之间的区别
如果您真的想,您可以尝试分析函数的源代码并确定它是否有任何返回语句,如果没有,则假定它不会返回值。当然,要确定一个函数是否有时返回,而其他函数是否返回(例如if块中的return语句)不,您无法通过跨浏览器可靠地判断函数是否仅通过到达其代码末尾、使用
return
不带值或使用return undefined
返回。这在本规范的第1部分中有所涉及
这里的另一个答案建议您可以通过分析函数的源代码来实现。然而,没有标准的机制来做到这一点。尽管几乎所有的浏览器都可以从
函数#toString
中获得某种形式的源代码,但有些浏览器没有(大部分是移动浏览器),并且规范中也没有对其进行定义。但是,如果您有一组您支持的浏览器,并且它们都有,这将是您唯一的实际选择-但即使这样,您也不一定知道函数中采用了哪个代码分支。您只能知道是否通过包装器调用函数,但我不确定这是否适合您的用例
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());
这是疯狂的,绝对不推荐,它创建函数的副本,修改函数体并使用
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)
第一个参数是函数本身,第二个参数是参数数组
返回值将是一个具有两个属性的对象,out
包含函数结果,returned
是一个布尔值,指示函数是否返回
示例输出
returnProxy(someFunction,[1]); // {out: undefined, returned: true}
returnProxy(someFunction,[2]); // {out: "hello", returned: true}
returnProxy(someFunction,[3]); // {out: undefined, returned: false}
我认为这是不可能的。我很好奇:用例是什么?你为什么关心a、b或c中的哪一个发生了?它们在功能上是相同的。没有区别的区别就是没有区别…:-)不要忘记
返回
和返回void
,这也会给出未定义的
。如果您在解释源代码之前有权访问源代码,您可以将最终的}
替换为返回someConst代码>其中someConst
是用户不太可能返回的内容,然后从包装器返回undefined
。@T.J.Crowder这确实是一个非常独特的用例,它是游戏的一部分,其中涉及到编码-根据使用的代码,会发生不同的事情。我只是在测试一些想法,以前从未遇到过这个问题。但是,我的回答和我预期的一样令人难过。。从JS的视角来看,这是一个微妙的烦恼。看来我必须尝试另一种方法。请您解释一下ainvoker.called()如何从binvoker.called()返回不同的值?我也考虑过这种方法,但我不认为它实际上解决了这个问题。它计算了它被调用的次数。我假设它仍然认为javascript不是多线程的,所以如果call()完成,它将增加调用1,并从a()或b()返回。区别在于ainvoker.called()==1和binvokver.called()==0。但是我可能遗漏了一些东西……@rene建议返回actualFunc()
toreturnactualfunc.apply(这是参数)
也许你是故意选择将其命名为call
,但这似乎你忘记了invokerinstance。call
应该有不同的含义。+1谢谢你的回答,非常正确,但我真的希望在这一层面上避免任何事情。。如果js有某种形式的释放能力或定义默认返回值的方法就好了。+1谢谢。是的,我开始走这条路,但后来开始意识到会涉及到什么,基本上以几乎重新解析所涉及的代码结束:我喜欢这样只是因为它的疯狂!