Is it possible to find out if a function is using an empty return statement?

Is it possible to find out if a function is using an empty return statement or is simply not using the return keyword?

For example:

function noReturn(){ }
function useReturn(){ return; }

console.log( noReturn() );   // undefined
console.log( useReturn() );  // undefined

      

I know all about WHEN and WHY that will use an empty return statement, I just want to know if you can tell if it was used return;

at all or not.

I guess this is not possible and that's okay. If there was some cool function prototype trick that I didn't know about, that would be nice.


Edit: Don't try to solve any specific problem unless general curiosity is the problem. :)
+3


source to share


4 answers


You cannot distinguish between the return values ​​of these three functions:

function a() { }
function b() { return; }
function c() { return undefined; }

      



according to the JS spec.

+2


source


I think this is a toy issue, but here is a possible approach to this issue. Convert the function to a string, and then, for all instances of a valid return statement, anywhere in the line, replace them with confederate return statements. Execute this modified function with eval()

and see what is returned.

For example,

function foo(){ return; }
function bar(){ if(0) return; }

      

becomes

function foo(){ return 'return;'; }         // "return;"
function bar(){ if(0) return 'return'; }    // undefined

      

This way, whatever path the logic follows in a function, if something is explicitly returned, we can know what form it takes. If nothing is returned, "undefined" is returned due to design or logic flow. Consider the following function:



function inspectReturn(fcn) {
  var str = fcn.toString();

  // Anytime we see a 'return something' we replace it with return 'something'
  str = str.replace(/(\b)return \s*(\S[^\n;}]+)/mg, "$1return '$2'");

  // Anywhere we see a lone 'return' we replace it with return 'return'
  str = str.replace(/(\b)return\s*([\n;}])/mg, "$1return 'return;'$2");

  eval("fcn="+str);
  return fcn();
}

      

We can then observe the return values ​​from the sample functions below:

function noReturn(){ }                     // undefined
function useReturn(){ return }             // "return;"
function useReturn2(){ return; }           // "return;"
function useReturn3(){ return true; }      // "true"
function useReturn4(){ if(0) return; }     // undefined
function useReturn5(){ return undefined }  // "undefined "
function useReturn6(){ var _return = " return "; return _return; }  // "_return"

      

Demo: JSBin


Note. Voice your opinion on how the regex can be improved as you wish. You can break it (and congratulate it), but there are simple and specific JavaScript parsing rules for validating return statements , so such a toy problem is for the reader to implement them correctly. Also, if there is something thrown

, there are blocks for that catch

. However, this is a sufficient demonstration IMHO.

+1


source


No, it is impossible to distinguish:

  • return undefined;

  • return;

  • End of function without returning a value

First, both return undefined;

and return;

return the same:

12.9 Operator return

ReturnStatement:

  • return

    ;

  • return

    [no LineTerminator here] Expression ;

Operator

A return

causes the function to stop executing and return a value to the caller. If no expression is specified, the return value is undefined . Otherwise, the return value will be the value of the expression.

The ReturnStatement function is evaluated as follows:

  • If the expression is not present, return (return, undefined, empty).
  • Let exprRef be the result of evaluating an expression.
  • Return (return, GetValue (exprRef), empty).

And then it doesn't matter if you used return;

or nothing, because it [[Call]]

will return undefined

:

13.2.1 [[Call]]

  1. If result.type is throw, then throw result.value.
  2. If result.type is a return, then we return result.value.
  3. Otherwise, result.type should be normal. Return undefined .
+1


source


Unaware that JavaScript doesn't distinguish them. The verification method can be:

function noReturn(){ }
function useReturn(){ return; }
function foo(){ 
  var _return = "return";
}
function fooReturn(){ 
  var _return = "return";
  return _return; 
}
function fooReturn2(){ 
  var _return = "return";
  return; 
}


console.log(/return\s*(\w*);?\s*}\s*/.test(noReturn.toString())); //false
console.log(/return\s*(\w*);?\s*}\s*/.test(useReturn.toString())); //true

console.log(/return\s*(\w*);?\s*}\s*/.test(foo.toString())); //false
console.log(/return\s*(\w*);?\s*}\s*/.test(fooReturn.toString())); //true
console.log(/return\s*(\w*);?\s*}\s*/.test(fooReturn2.toString())); //true
      

Run codeHide result


0


source







All Articles