Вопрос

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.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top