JavaScript eval() "syntax error" on parsing a function string

23,557

Solution 1

To do what you want, wrap your string in parentheses:

a = "function(value) { return Math.abs(value);}";
b = eval("("+a+")");
b(-1);

Solution 2

The parentheses are required because they force the thing inside them to be evaluated in an expression context, where it must be a function-expression.

Without the parentheses, it could instead be a function declaration, and it seems as if it is sometimes being parsed that way - this could be the source of the odd/inconsistent behaviour you're describing.

Compare this function declaration:

function foo(arg) {}

with this function-expression:

var funcExpr = function foo(arg) {};

It also has to be a function-expression if it doesn't have a name. Function declarations require names.

So this is not a valid declaration, because it's missing its name:

function (arg) {}

but this is a valid, anonymous function-expression:

var funcExpr = function(arg) {};
Share:
23,557
Kenny Peng
Author by

Kenny Peng

“Those parts of the system that you can hit with a hammer are called hardware; those program instructions that you can only curse at are called software.”

Updated on January 31, 2020

Comments

  • Kenny Peng
    Kenny Peng over 4 years

    I have a bit of JavaScript code that is specified in a configuration file on the server-side. Since I can't specify a JavaScript function in the configuration language (Lua), I have it as a string. The server returns the string in some JSON and I have the client interpret it using a clean-up function:

    parse_fields = function(fields) {
        for (var i = 0; i < fields.length; ++i) {
            if (fields[i].sortType) {
                sort_string = fields[i].sortType;
                fields[i].sortType = eval(sort_string);
            }
            return fields;
        }
    }; 
    

    So basically it just evaluates sortType if it exists. The problem is that Firebug is reporting a "Syntax error" on the eval() line. When I run the same steps on the Firebug console, it works with no problems and I can execute the function as I expect. I've tried some different variations: window.eval instead of plain eval, storing the sortType as I've done above, and trying small variations to the string.

    A sample value of fields[i].sortType is "function(value) { return Math.abs(value); }". Here's the testing I did in Firebug console:

    >>> sort_string
    "function(value) { return Math.abs(value); }"
    >>> eval(sort_string)
    function()
    >>> eval(sort_string)(-1)
    1
    

    and the error itself in Firebug:

    syntax error
    [Break on this error] function(value) { return Math.abs(value); }
    

    The last bit that may be relevant is that this is all wrapped in an Ext JS onReady() function, with an Ext.ns namespace change at the top. But I assumed the window.eval would call the global eval, regardless of any possible eval in more specific namespaces.

    Any ideas are appreciated.

  • Kenny Peng
    Kenny Peng about 14 years
    Yep, that worked. Why are the parentheses required when Firefox executes the code outside of the Firebug interface, but not required when using the Firebug console?
  • Jasper
    Jasper about 14 years
    I, for one, can't get it to work without the braces even in the Firebug console. I don't know why it would work for you. What version of Firebug are you using?
  • Andy E
    Andy E about 14 years
    @Kenny Peng: I remember wondering this myself once and found this answer to a similar question: stackoverflow.com/questions/964397/…. This was my first thought when I saw the question, +1 to @jhurshman for his answer.
  • Kenny Peng
    Kenny Peng about 14 years
    @Jasper: I was using Firebug 1.5.3.
  • Jasper
    Jasper about 14 years
    @Kenny: I am using 1.5.4, so perhaps something has change. I can but guess about why it is working in your commandline, but it is probably a tricky matter anyway, seeing that the commandline is doing an eval (or something similar) on what you typed already...
  • loretoparisi
    loretoparisi about 8 years
    That's old school, super awesome!