Lokomotywa
Lokomotywa

Reputation: 2844

Eval function expression

While I was expecting that this code

var  a = eval("function() { return 1; }");

console.log(a());

prints '1' in the console, I get a syntax error Uncaught SyntaxError: Unexpected token (. What am I doing wrong here?


I am working with a framework that allows to define javascript functions in the configuration, so I have no other choice but using eval.

Upvotes: 0

Views: 132

Answers (4)

VLAZ
VLAZ

Reputation: 29086

The problem is that you have a function declaration and that requires a name. For reference, this is a function declaration

function myFunc() { console.log("executed") } //<-- declaration

myFunc(); //<-- execution

What you expect to have is an unnamed function expression

var myFunc = function() { console.log("executed") }
//expression ^------------------------------------^

myFunc(); //<-- execution

Or for a truly unnamed function that you do not assign to a variable, you can have an IIFE

// v--------- brackets surrounding expression ---------v
   (            function() { console.log("executed") } )()
//expression    ^------------------------------------^  ^^
//execution  -------------------------------------------++

However, in JavaScript a standalone statement that starts with the function keyword will be treated as declaration and if it doesn't have a name, it is invalid.

However, you can go around that by surrounding the expression in brackets to make it acceptable for the parser.

//brackets    v--------------------------v
var a = eval("( function() { return 1; } )");
//              ^----------------------^ function expression
console.log(a());

Upvotes: 2

georg
georg

Reputation: 215029

The function keyword is ambiguous in Javascript: it can start a function declaration (a statement), or a function literal (an expression). When function is encountered in the statement position, the parser voluntarily prefers declaration over expression. Since eval expects a statement, this makes your code invalid -- function name is required for declarations. You can either provide a name:

eval('function foo() {...}')

or force the parser into the expression mode

foo = eval('( function () {...} )')

in which case function will be treated as a literal.

This is basically the same story as with {}, which can be either a block or an object literal. Something like eval('{1:2}') will fail for exactly the same reason (statement preferred over expression).

Upvotes: 4

Shilly
Shilly

Reputation: 8589

You cannot mix function declaration and function expressions this way. You have to do the full declaration or expression inside the eval().

 eval("function a() { return 1; }");
 console.log(a());

This would work, as we give the function declaration a proper name, a, and then call the function this creates on the global scope.

 eval("var a = function() { return 1; }");
 console.log( a() );

This would also work, since the function expression assigning it to the variable a is now part of what gets evaluated. And we can then call the function in it's scope.

Neither of these should actually ever be used if there's alternatives. The most common alternative is using new Function();.

var a = new Function( 'return 1;' );
console.log( a() );

This achieves the same end result and is slightly safer than using eval().

I would be surprised though if this was the only way the framework allows to define extra javascript functions. I guess that since it's in the config of something the security issues this gives are less important than if it's public code. But i would reread the docs of the framework to double check that this is the only option.

Upvotes: 1

Kai Lehmann
Kai Lehmann

Reputation: 508

As the comments are 100% true that a function must contain a name or has to be initialised as an anonymous function, there is a solution to your problem.

If you want to create a function by text you could use the function constructor

new Function ([arg1[, arg2[, ...argN]],] functionBody)

For more information look at https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Function

Upvotes: 1

Related Questions