admin管理员组文章数量:1336631
I'm currently writing some code that wrappers user-written JavaScript functions, and have e across a point in the logic where I would like to trigger a particular behaviour if the function in question never returns a value i.e. the return
keyword is never evaluated.
Currently I am assuming that if a function returns undefined
, it has not returned, however this is not strictly true—due to the fact a function can always return undefined
, or return the value of an undefined property.
With a function call you can always tell how many parameters were used due to the arguments.length
property, I was wondering if anyone knew of a similar trick for a function's return value?
So, is it possible to tell the difference between the return values of a
, b
or even c
var a = function(){ };
var b = function(){ return undefined; };
var c = function(){ if(1){}else{return undefined;}; };
I'm currently writing some code that wrappers user-written JavaScript functions, and have e across a point in the logic where I would like to trigger a particular behaviour if the function in question never returns a value i.e. the return
keyword is never evaluated.
Currently I am assuming that if a function returns undefined
, it has not returned, however this is not strictly true—due to the fact a function can always return undefined
, or return the value of an undefined property.
With a function call you can always tell how many parameters were used due to the arguments.length
property, I was wondering if anyone knew of a similar trick for a function's return value?
So, is it possible to tell the difference between the return values of a
, b
or even c
var a = function(){ };
var b = function(){ return undefined; };
var c = function(){ if(1){}else{return undefined;}; };
Share
Improve this question
asked Dec 1, 2012 at 10:41
PebblPebbl
36.1k6 gold badges64 silver badges65 bronze badges
5
- I think this is not possible. – Pavel Strakhov Commented Dec 1, 2012 at 10:45
- I'm curious: What's the use case? Why do you care which of a, b, or c occurred? They are functionally identical. A difference that makes no difference is no difference... :-) – T.J. Crowder Commented Dec 1, 2012 at 10:53
-
Don't forget
return;
andreturn void <expr>
which also giveundefined
. – Paul S. Commented Dec 1, 2012 at 11:03 -
If you have access to source before it gets interpreted, you could replace the final
}
withreturn someConst;
wheresomeConst
is something very unlikely to be returned by the user, then returnundefined
from your wrapper. – Paul S. Commented Dec 1, 2012 at 11:09 - @T.J.Crowder it's really rather a singular use-case, it's part of a game where coding will be involved - and different things will occur depending on the code used. I was just testing out a few ideas and had not e across this issue before. The responses are sadly as I expected though.. rather a subtle annoyance from JS's pov. Ah well c'est la vie :) Looks like I'll have to try a different approach. – Pebbl Commented Dec 1, 2012 at 12:01
5 Answers
Reset to default 4No, you cannot reliably, cross-browser, tell whether a function returned by just reaching the end of its code, using return
without a value, or using return undefined
. This is covered by Section 13.2.1 of the specification.
Another answer here suggests you could do it by analyzing the source code of the function. However, there is no standard mechanism for doing that. Though nearly all browsers make some form of the source available from Function#toString
, some do not (mostly mobile browsers), and it is not defined by the specification. But if you have a certain set of browsers that you support, and they all have it, that would be your only real option — but even then, you wouldn't necessarily know which code branch was taken within the function.
Leaving a function blank will also return undefined, so a, b and c will all return identical values.
The only way to achieve something like this would to actually set some kind of flag in the function itself, but I'm guessing you want to be able to do this independently of the implementations of the actual function.
There is no way to tell the difference.
If you really wanted to, you could try to analyze the function's source code and determine whether it has any return statements, and if not, then assume it won't return a value. Of course this would be a bit harder to determine if a function sometimes returns and others not (eg. a return statement in an if-block)
This is crazy and definitely not remended, it creates a copy of the function, modifies the function body and uses 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)
}
}
Assuming you have a function like this,
function someFunction(action) {
switch(action) {
case 1:
return undefined;
case 2:
return "hello";
}
}
You would use the proxy function like this:
returnProxy(someFunction,[1]); // instead of calling someFunction(1)
With the first parameter being the function itself , and second parameter an array of parameters
The return value will be an object with 2 properties, out
contains the function result, and returned
is a boolean indicating if the function returned or not
Example output,
returnProxy(someFunction,[1]); // {out: undefined, returned: true}
returnProxy(someFunction,[2]); // {out: "hello", returned: true}
returnProxy(someFunction,[3]); // {out: undefined, returned: false}
You can only tell if you invoke the functions through a wrapper, but I'm not sure if this is suitable for your usecase.
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());
本文标签: Any way to tell whether a javascript function has returned or notStack Overflow
版权声明:本文标题:Any way to tell whether a javascript function has returned or not? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742407527a2469128.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论