16

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
  • 1,891
  • 4
  • 18
  • 26
  • 3
    Note that IE cannot eval functions. – SLaks May 03 '10 at 20:24
  • try `var foo = function(value) { ... }` – Gordon Gustafson May 03 '10 at 20:26
  • @SLaks: `eval` works just fine for me in IE for the above string, no errors... as does `eval("a = function () { return 'b'; }")` -- can you clarify what you meant please? – Andy E May 03 '10 at 20:36
  • @Andy: Paste `javascript:alert(eval("(function() { return 4; })"))` into the address bar in FF and IE. – SLaks May 03 '10 at 21:07
  • @SLaks: that is interesting. What's weird is that when you call the function inside the `eval` expression, it works: `javascript:alert(eval("(function() { return 4; })()"))`. So it seems that IE can `eval` functions, it just has problems returning them as the result. Your point is very valid for this question since the OP's source won't work in IE, but it looks like there are workarounds. – Andy E May 04 '10 at 08:06
  • 1
    To eval functions in all browsers, use `eval("[function(){return 1}][0]");` See my comment on http://stackoverflow.com/questions/4599857/is-eval-and-new-function-the-same-thing/4599932#4599932 – Ruan Mendes May 18 '11 at 22:06

2 Answers2

43

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

a = "function(value) { return Math.abs(value);}";
b = eval("("+a+")");
b(-1);
jhurshman
  • 5,861
  • 2
  • 26
  • 16
  • 2
    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? – Kenny Peng May 03 '10 at 20:32
  • 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? – Jasper May 03 '10 at 20:39
  • 1
    @Kenny Peng: I remember wondering this myself once and found this answer to a similar question: http://stackoverflow.com/questions/964397/why-does-javascripts-eval-need-parentheses-to-eval-json-data/964437#964437. This was my first thought when I saw the question, +1 to @jhurshman for his answer. – Andy E May 03 '10 at 20:41
  • @Jasper: I was using Firebug 1.5.3. – Kenny Peng May 03 '10 at 20:43
  • @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... – Jasper May 03 '10 at 21:05
  • That's old school, super awesome! – loretoparisi Apr 08 '16 at 09:35
5

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) {};
Aliaksei Kliuchnikau
  • 13,589
  • 4
  • 59
  • 72
whatever
  • 51
  • 1
  • 1