I'm using the following function named isExpression
to determine whether some JavaScript code is an expression:
function isExpression(code) {
try {
new Function("return " + code);
return true;
} catch (e) {
return false;
}
}
It works correctly for all test cases except one - it incorrectly treats a FunctionDeclaration
as a FunctionExpression
and returns true
instead of false
. Is there some way to fix this problem without having to write a parser?
As @FelixKling pointed out the only way to determine if a function is a declaration and not an expression is to check the context of the function. However in a REPL (for which the isExpression
function is intended) there is no context. Thus matters become simpler.
The code
typed into a REPL can only be a function declaration if it starts with the keyword function
(after trimming whitespace in the beginning). Hence it can be tested by the regular expression /^\s*function\s/
.
@FelixKling points out that such a function may still be an expression and not a declaration depending upon the context of the function (i.e. the function is an expression if it's a non-source element). However the code
passed to this function is guaranteed to be a source element.
If such a function construct were to be used as an expression using the conditional operator (e.g. function f() {} ? x : y
) or using the comma operator (e.g. function f() {}, x
) then isExpression
would still return false
. However such code would raise a SyntaxError
. Hence the following implementation of isExpression
will correctly test whether some code is an expression for all cases:
var isExpression = function (functionDeclaration) {
return function (code) {
if (functionDeclaration.test(code)) return false;
try {
Function("return " + code);
return true;
} catch (error) {
return false;
}
};
}(new RegExp(/^\s*function\s/));