Determine if JavaScript code is an expression
-
25-06-2021 - |
Вопрос
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/));
Другие советы
By checking the type of the value returned by your constructed function we can determine that the original expression was a function.
function isExpression(code) {
try {
return typeof (new Function("return " + code)) () !== 'function';
} catch (e) {
return false;
}
}
Caveat : calls in the string will be invoked. This may make this less useful.