views:

28

answers:

4

Hello everybody.

I working with jQuery and i needed to generate an anonymous method with the eval() function.

The following lines worked with Opera but not with IE, FF, Chrome:

var callbackStr = "function(){alert('asdf');}";  
var callback = eval(callbackStr);  
callback();

This code works with all Browsers:

var callbackStr = "var callback = function(){alert('asdf');}";  
eval(callbackStr);  
callback();  

You see, I already solved my problem. But I want to know, what exactly is happening. Can anybody explain this behaviour to me, or tell me where i can find further information?

(PS: I know this page.)

+1  A: 

eval does not return the function like that. Instead it executes a piece of code in the global scope, thats why the second example works - the callback var has been created in the global scope.

I'm sure these are just extremely simplified examples but you can almost always avoid using eval in the first place, which is recommended.

Jake
I'm working with jQuery. I need to dynamically generate some callback functions to pass them as parameters to the autocomplete plugin. I know that this solution is quite ugly. I guess I will think twice about it...
Chrigl
A: 

The first case simply evaluates your string and executes the function. It does not return a pointer to that particular function, that's why you cannot execute it by calling callback.

mamoo
+1  A: 

the first example will work if you'll do your eval like this

var callbackStr = "function(){alert('asdf');}";  
var callback = eval("(" + callbackStr + ")");  
callback();
rob waminal
+4  A: 

The reason is the same as the reason you need to wrap parentheses around JSON strings before using eval on them - eval treats { as a token, the start of a statement eval assumes the anonymous functions is a FunctionDeclaration. Using parentheses allows eval to treat what's inside as an expression:

var callbackStr = "(function(){alert('asdf');})";  
var callback = eval(callbackStr);  
callback();
// -> alerts 'asdf';

As for why Opera behaves differently here, I have no idea. As for your use of eval, there's probably a better way (there nearly always is).

I dug out a quote from the spec for you, section 12.4 of ECMA-262 3rd Edition:

Note that an ExpressionStatement cannot start with an opening curly brace because that might make it ambiguous with a Block. Also, an ExpressionStatement cannot start with the function keyword because that might make it ambiguous with a FunctionDeclaration.

Emphasis mine.

Andy E
It's not exactly that `eval` assumes that the statement inside is a FunctionDeclaration; it's that the statement inside an `eval` string must match the Statement production from the ECMA-262 standard. That production doesn't allow you to begin a statement with `function(`, because of the section you quoted.
Daniel Martin