I am doing :
eval('function(){ console.log("Hello World"); }')();
But that gives error :
Uncaught SyntaxError: Unexpected token (
Why is this wrong?
The eval operator expects a Program as input, and the grammar of JavaScript requires that all
top-level program elements are either declarations or statements.
The spec says:
Let prog be the ECMAScript code that is the result of parsing x as a Program.
function can't start a top-level statement, but it can start a function declaration, but only when it has a name.
That's why you get "Unexpected token ("; it expects a function name before the parenthesis that opens the argument list.
As others have noted, to eval a function, you need to trick the JavaScript parser into finding an expression where it expects a statement. Wrapping the body in parentheses is one way to do this.
eval expects a statement but:
function(){} is not valid as a statement because the function name is missing.
(function(){}) is instead recognized because the statement is a "statement expression".
The problem is that function as first token triggers the function declaration rule when a statement is expected. When an expression is expected instead (e.g. inside parenthesis) then function triggers the function expression rules where a name is optional but not mandatory.
What you want is this:
eval( '(function(){ console.log("Hello World"); })()' );
Let's break it down. You have a self invoking function (a function that calls itself):
(function(){ console.log("Hello World"); })()
And you're passing it as a string argument to the eval method:
eval( '(function(){ console.log("Hello World"); })()' );
Your main error is trying to call what eval returns by adding parenthesis on the end of the eval method call. If you want the function your passing to immediately invoke itself, the added parenthesis should be part of the thing your passing to eval.
I'm assuming you're trying to do something other than call "Hello World", as you could simply do this:
eval( 'console.log("Hello World");' );
Or, dare I say:
console.log("Hello World");
Related
I'm trying to immediately invoke a function without using IIFE pattern (enclosing a function definition inside parentheses). Here I see two scenarios:
When a function declaration is invoked immediately: gives SyntaxError.
When a function expression is invoked immediately: executes successfully.
Example 1: gives SyntaxError
//gives `SyntaxError`
function() {
console.log('Inside the function');
}();
Example 2: Executes without any error
// Executes without any error
var x = function() {console.log('Inside the function')}(); // Inside the function
So, I have these doubts:
With this approach, why does it give an error for function declaration but not for function expression?
Is there a way we can immediately invoke a function declaration without using IIFE pattern?
In your code you don't have name for the function that's the reason for syntax error. Even if you would had name it would have thrown error.
function func(){
console.log('x')
}();
The reason is the function declaration doesn't return the values of the function however when you wrap function declaration inside () it forces it be a function expression which returns a value.
In the second example the function() {console.log('Inside the function')} is considered expression because it's on RightHandSide. So it executes without an error.
Is there a way we can immediately invoke a function declaration without using IIFE pattern
You can use + which will make function declaration an expression.
+function(){
console.log('done')
}()
If you don't want to use + and () you can use new keyword
new function(){
console.log('done')
}
Extra
A very interesting question is asked by #cat in the comments. I try to answer it.There are three cases
+function(){} //returns NaN
(+function(){return 5})() //VM140:1 Uncaught TypeError: (+(intermediate value)) is not a function
+function(){return 5}() //5
+function(){} returns NaN
+ acts as Unary Plus here which parses the value next to it to number. As Number(function(){}) returns NaN so it also returns NaN
(+function(){return 5;})() returns Error
Usually IIFE are created using (). () are used to make a function declaration an expression + is short way for that. Now +function(){} is already an expression which returns NaN. So calling NaN will return error. The code is same as
Number(function(){})()
+function(){return 5;}() returns 5
In the above line + is used to make a statement an expression. In the above example first function is called then + is used on it to convert it to number. So the above line is same as
Number(function(){return 5}())
In the proof of statement "+ runs on after the function is called" Consider the below snippet
console.log(typeof +function(){return '5'}());
So in the above snippet you can see the returned value is string '5' but is converted to number because of +
A function declaration, like
function foo() {
}
defines (and hoists) the variable name foo as a function in the current scope. A function declaration doesn't evaluate to a value; it just does something, a bit like an if does something (rather than evaluate to a value).
You can only invoke values which are functions, eg
<somevalue>()
where somevalue is a variable name that refers to a function.
Note that function declarations require function names, because otherwise there's no variable name to assign the function to - your original
//gives `SyntaxError`
function() {
console.log('Inside the function');
}();
throws not because of the () at the end, but because of the lack of a name.
You can put parentheses at the end of a function declaration, as long as there's something inside the parentheses - but these parentheses do not call the function, they evaluate to a value:
function x() {
console.log('Inside the function');
}(console.log('some expression inside parentheses'));
The interpreter sees these as two separate statements, like
function x() {
console.log('Inside the function');
}
// completely separate:
(console.log('some expression inside parentheses'));
The inside of the parentheses gets evaluated and then discarded, since it doesn't get assigned to anything.
(Empty parentheses are forbidden because they can't be evaluated to a value, similar to how const foo = () is forbidden)
The E in IIFE stands for expression, and without the wrapping parenthesis your function is not evaluated as an expression thus the syntax error.
creating an expression is a way of tricking the interpreter and be able to invoke the function immediatly
(function() {
console.log('Inside the function');
})();
In your example you have a function statement followed by the grouping operator, but it's syntactically incorrect for two reasons, first it doesn't have a name, and second because the grouping operator must have an expression inside it, infact if you add a valid one the error will disappear, still you won't obtain your desired result.
function foo() {
console.log('Inside the function');
}();
function foo() {
console.log('Inside the function');
}(1+2);
In order to invoke something, it has to be a function value, a declaration just declares a name, and does not evaluate to the function value itself, hence you cannot invoke it.
A declaration cannot be invoked for the above reason. You have to end up with an expression somehow, either through assignment or grouping (IIFE). So that is a no.
If you give us more context on why you would want to do that, maybe we can help with suggestions.
Not sure why you would want to do it, but:
Is there a way we can immediately invoke a function declaration without using IIFE pattern?
Well, if for function declaration you mean using the keyword function as in:
function name() { return this.name; }
As far as I know, no. You need the extra parentheses to tell the runtime not to assign the function to a name variable, if I understand this stuff right.
Now, what you actually can do is to use Function as in:
new Function('console.log("ey there")')();
Which will execute the console.log code. No need for IIFE here. But I don't see how this could be better than an IIFE.
you can call in either below ways -
~function(){console.log("hi")}()
!function(){console.log("hi")}()
+function(){console.log("hi")}()
-function(){console.log("hi")}()
(function(){console.log("hi")}());
var i = function(){console.log("hi")}();
true && function(){ console.log("hi") }();
0, function(){ console.log("hi") }();
new function(){ console.log("hi") }
new function(){ console.log("hi") }()
If I put a function into a string like this:
var functionString = function (message) {
console.log(message);
}.toString();
Is there any way to convert the string back to a function and call it?
I tried
eval(functionString)
which returns "Uncaught SyntaxError: Unexpected token", and
functionString.call(this, "HI!");
which returns 'undefined is not a function'.
Is that even possible in javascript?
Thanks in advance for any reply!
EDIT: The point of this question is that the function has been converted into a string using toString(). So
console.log(functionString);
returns this string:
"function (message) {console.log(message);}"
Can I transform the string back into a function and call it? That's the problem I am trying to solve.
Thanks!
You're nearly there, but you're missing something.
When we call toString() on your function, we get
"function (message) {
console.log(message);
}"
which we can then eval. However, we're just creating an anonymous function object here; we won't be able to call it!
If we instead to something like:
var functionString = "var restoredFunc = " + function (message) {
console.log(message);
}.toString();
We can then do the following
eval(functionString);
// prints "hello!" to console
restoredFunc("hello!");
Your functionString contains exactly the string
"function (message) { console.log(message); }"
Evaluating it as-is does present JavaScript engine with incorrect syntax (there is no name for this function). JavaScript expects construct like function <name>(<params>) { }. Alternatively, you can use anonymous function (i.e. no name present), but only as a parameter or in a context of evaluating expression. The minimal typical evaluating expression would be (function() {})() If you want to get fancy, !function() {} is also ok - the exclamation mark in front turns it into boolean expression that requires function evaluation before negating the output.
So, in your example this will work:
eval("("+functionString+")('abc')");
because then you do anonymous function call - something JavaScript can live with.
Alternatively, you can also use just brackets, then you need to assign the result to something you can use later:
var foo = eval("("+functionString+")");
foo('ddd');
Here is a little proof / playground to learn about it:
http://jsfiddle.net/Exceeder/ydann6b3/
yes its possible in JavaScript but you can't eval anonymous function without assignment
So you go through it like so
var functionString = function (message) {
console.log(message);
}.toString();
eval("myfunction =" + functionString)
myfunction("Hello World!")
Your functionString is a string that looks like
"function (message) {
console.log(message);
}"
You could covert that string to an Immediately-Invoked Function Expression (IIFE) using string concatenation, similar to below.
(function (message) {
console.log(message);
})("HI!");
and then eval that. Here is the result from Chrome's JavaScript console:
eval('(' + functionString + ')("HI!")')
HI!
I just spend long time digging through callbacks in promises wondering why some callbacks are not called. In the end problem was with incorrect declaration, instead of
Promise.when(null).then(function () {
var p = new Promise();
p.fail(new Error("some message"));
return p;
}).then(function () {
console.log("success");
}, function (err) {
console.log("failure");
});
I did
Promise.when(null).then(function () {
var p = new Promise();
p.fail(new Error("some message"));
return p;
}).then(function () {
console.log("success");
}), function (err) {
console.log("failure");
};
Regardless of Promise implementation details it boils down to one thing:
function(){};//throws SyntaxError
"something valid, or function call", function(){};//no error
I would like someone to explain this to me. Why first is throwing SyntaxError while latter is valid (at least in browser console)? It seems to declare anonymous function.
Same thing happens when I try
eval("function(){};//throws SyntaxError")
eval("'lala',function(){};//no error")
So can someone explain me why first is not valid while latter is ?
A statement that begins with the keyword "function" must be a valid function declaration statement. That requires a name for the function.
In an expression (or expression statement), that rule is different; no name is necessary because the function acts as a value in that context. No name is required then.
Thus this:
function myFunction() {
// ...
}
is a function declaration statement. This:
5 + function() {};
is an expression statement (a silly one, but JavaScript is ok with that). Similarly, your example that results in no error is an expression with the comma operator:
"lala", function() {};
The keyword "function" does not appear at the beginning of either of those two expressions, so the parser does not insist on a name for the function.
Your original code was not working because, as you figured out, the second function was not passed as a parameter - you put the closing paren before the function. It was causing no error because JavaScript recognized it as a function expression. Your use of the comma operator told JavaScript to expect the next statement to be an expression.
A function declaration cannot be anonymous, but a function expression can. A stand alone anonymous function looks like a function declaration that is missing an identifier to JavaScript. But, combined with an operator, JavaScript treats an anonymous function as the operator's operand expression.
The statement 'lala',function(){} consists of an expression ('lala') followed by an operator (,) followed by a function expression. This statement is similar: 0,function(){}. Promise.when(...).then(...) is also a valid expression, so Promise.when(...).then(...),function(){} works just the same.
Why does this return a syntax error:
function(foo){console.log(foo)}
I'd expect this to return the value of the function, hence return itself, and not assign it to anything, but i get a "SyntaxError: Unexpected token ("
but this works:
(function(foo){console.log(foo)})
Please explain what purpose those wrapping parenthesis serve. I've been told that parens are used to "increase readability" but in this case there definitely is more purpose served.
Can you please go into further detail about use about () ? Say you were to translate that line of code to prose, what would the () read like? I am trying as well to describe this concept to other people, and need to transmit its meaning so that everybody can understand it. The question i'm trying to answer, is what do the ()'s mean? Do they have a semantic value, and what is it?
Your first example is a function declaration. It doesn't have an identifier, which is a syntax error. Here's the grammar for a function declaration (notice that Identifier is not optional):
FunctionDeclaration :
function Identifier ( FormalParameterListopt ) { FunctionBody }
By wrapping it in parentheses you turn it into a function expression (an anonymous one). You could execute it by adding a pair of invoking parentheses after:
(function(foo){console.log(foo)})("hello"); //Will log 'hello'
Here's the gammar for a function expression (now the identifier is optional):
FunctionExpression :
function Identifieropt ( FormalParameterListopt ) { FunctionBody }
How the parentheses turn a function declaration into a function expression
In this case, the parentheses are parsed as a "grouping operator". The grammar for the grouping operator is as follows:
PrimaryExpression :
( Expression )
The grouping operator can only contain an expression, so your function is parsed as an expression rather than a declaration (obviously, in your exact example, the function can't be a declaration since it doesn't have an identifier).
This is because without the (), the function(){} line is a function declaration, while with the () is an expression.
function declarations are a strange beasts, they made available everywhere in the scope they are defined in before code execution, so snippets like this works:
foo();
function foo() { console.log('foo'); }
Why does the following code trigger "Expected an assignment or function call and instead saw an expression." in JSHint? I thought this was the correct way to protect a block from executing if a particular variable or variables are not defined...
!function($) {
"use strict";
// jQuery-based code here
$('.test').show();
}(window.jQuery);
Replace the ! in front of function with parens around the entire call (e.g. (function(a,b){}("a","b"))) and all should be well. Which prompts me to ask why it is there in the first place since the function returns no value.
Any expression, as opposed to assignment, is flagged by JSHint with the message you quote.