There is something I don't understand about how eval works. Suppose I have a function foo:
function foo() {
console.log("test");
}
And then I write
eval("foo()");
or
eval("foo" + "();");
The function foo is executed and I have "test" printed out. However, if I write:
eval("function foo() { console.log(\"foo\"); }();");
or
eval("function foo() { console.log(\"foo\"); }" + "();");
I get "SyntaxError: Unexpected token )". Why is that? I saw that when I pass the function name it is evaluated into the function's code, so I though it's supposed to be the same as "eval("foo" + "();");"
I'm using Chrome 27 if it makes any difference.
There is something I don't understand about how eval works. Suppose I have a function foo:
function foo() {
console.log("test");
}
And then I write
eval("foo()");
or
eval("foo" + "();");
The function foo is executed and I have "test" printed out. However, if I write:
eval("function foo() { console.log(\"foo\"); }();");
or
eval("function foo() { console.log(\"foo\"); }" + "();");
I get "SyntaxError: Unexpected token )". Why is that? I saw that when I pass the function name it is evaluated into the function's code, so I though it's supposed to be the same as "eval("foo" + "();");"
I'm using Chrome 27 if it makes any difference.
Share Improve this question asked Jul 3, 2013 at 11:54 BennyzBennyz 6232 gold badges18 silver badges36 bronze badges 3-
2
eval
is meant to evaluate expressions, the last example isn't a single expression. Add an operator to the function declaration and you're there. That saideval
-ing code like this is a terrible idea, so I'd suggest not to even begin to try and understand how it works – Elias Van Ootegem Commented Jul 3, 2013 at 12:01 -
actually,
eval
is totally irrelevant here - that code will fail just in the same way without it. – georg Commented Jul 3, 2013 at 12:38 -
@thg435: Yes, it will. In my answer I went into more detail, and explained why his last
eval
call actually contained a syntactically invalid statement – Elias Van Ootegem Commented Jul 3, 2013 at 12:47
6 Answers
Reset to default 4Because no answer is specific about why the last snippet fails, and nobody seems to be warning you for the dangers of eval
:
eval
, according to MDN:
A string representing a JavaScript expression, statement, or sequence of statements. The expression can include variables and properties of existing objects.
Your string, "function foo(){console.log('foo');}()"
actually consists of 2 statements, that make no sense to the JS engine. Well, the second one doesn't:
function foo(){console.log('foo');}//function declaration, fine
;//<-- js adds implied statement terminator
()//no invocation, because no function reference, group nothing ==> does not pute, raise error
That's why you have to turn your function declaration statement into an expression, by adding an operator. Typically, this is the grouping operator: ()
(function foo(){ console.log('foo')});
The function declaration is now an expression, everything (the grouping ()
included) can be seen as a statement, unless the code that follows belongs to the code above. In this case, the invoking parentheses clearly do, so the JS engine sorts it out for you.
For clarity, some say the preferred notation is:
(function f(){}());//<-- invoking parentheses inside group
Which makes sense, because the invocation is part of the statement, after all.
If you don't like all these parentheses, any operator will do:
~function(){}();//bitwise not
+function(){}();//coerce to number
Are all equally valid. Note that they will change the possible return values of the function expression.
(function(){}());//resolves to undefined
+function(){}();//resolves to NaN, because undefined is NotANumber
How your eval
could look, then, is any of the following:
eval("(function (){console.log('foo');}());");
eval("~function (){console.log('foo');}();");
eval("!function (){console.log('foo');}();");
And so on, and so forth...
Lastly, eval
evaluates code in the global scope, so any code eval
-ed containing functions can, and likely will, polute the global namespace. Mallicious code will also have access to everything, so be weary of XSS attacks and all other JS based techniques.
Bottom line, eval
is evil, especially since all browsers now support JSON.parse
natively, and for those that don't, there still is a tried and tested JSON2.js file out there.
Using eval
in strict mode does make things slightly safer, but doesn't prevent XSS attacks at all, the code can still manipulate the DOM, for example, and reassign exposed DOM references or objects.
Google "why eval is evil" if you want to find out more.
Also check the ECMAScript specs
function x() {}
is a statement, whereas everything else you're doing is an expression, and you can only evaluate expressions.
The other answers explain how you can turn this statement into an expression. Thought I'd let you know why you actually get an error, though. :)
eval("(function() { console.log(\"foo\"); })()");
This is called a self-executing anonymous function.
you would need to call
eval("function foo() { console.log(\"foo\"); };" + " foo();");
in order for this to work;
Put brackets around your function
eval("(function foo() { console.log(\"foo\"); })()");
It is like calling
(function foo() { console.log("foo"); })()
The main thing you should understand about eval is that it is evil. Don't use it... ever. There is always a way to achieve the same thing by dynamically creating a script document or by using a closure.
Read Douglas Crockford: JavaScript the good parts.
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744166184a4561313.html
评论列表(0条)