function wrapped in parens - javascript

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'); }

Related

Why use the `+` (plus) or `!` (logical not) operator in an IIFE?

I know the typical form of an IIFE is:
(function(){/* code */})()
However, recently I found a new one:
!function(){/* code */}()
+function(){/* code */}()
which also work as IIFEs.
I think in the first ! makes the value a boolean, so the code is equivalent to true(), and in the second + makes the value a number, so the code is the same as NaN()? But true() and NaN() cannot possibly work, while the above two forms work well.
How do those two forms of IIFE work?
The function keyword has a duel purpose. Depending on the context you use it in, it either starts a function declaration or a function expression.
Function declarations declare a (hoisted) local variable in the scope of the current function and assign the function to that variable.
Function expressions don't, they require that you do something with the function immediately. Common examples include assigning it to a property of an object, passing it as an argument to a function (i.e. making it a callback) or using it as an IIFE.
If you try to follow a function declaration with () then it will error.
function myFunction() {
console.log("Example");
}();
Only function expressions can be immediately invoked function expressions. (Well, arrow functions can too, but IIFEs are much older than them).
So to use an IIFE you have to do something to change the context the function keyword appears in so it is used to create an expression instead of a declaration.
The classic way is to wrap the function in parentheses.
(function myFunction() {
console.log("Example");
})();
But anything that makes it an expression will work.
Putting an operator (such as ! or +) in front of the function keyword will do that.
While ! will take the return value of calling the IIFE and turn it into a negated boolean and + will turn it into a number that isn't the point. There's nothing to the left hand side of the operator so that value is discarded.
It is just a way to make the function keyword create a function expression that can be turned into an IIFE.
Note that the key benefits of IIFEs are also provided by block scoped variables (let and const) and JavaScript modules, so there isn't much reason to use an IIFE at all in 2022.
In the cases of !function() {}() and +function() {}() JavaScript will first evaluate the right handside of the given statement/IIFE and then cast the return value of the IIFE to a boolean in case of ! or to type number in case of +.
If the IIFE returns a boolean ! will negate the return value.
Example
console.log(
!function() {
return "something";
}()
);
/**
!function() {
return "something";
}()
evaluates to
!"something" and not true() or false()
lastly !"something" is equivalent to false
*/
There are many ways to get a function to execute immediately upon its definition. The common thing is that you must make sure the function is not interpreted as a function statement, but as a function expression.
By prefixing the function keyword with a unary operator like ! or + or any other unary operator (~, -, void, ...etc) you avoid that the function is interpreted as a statement.
Also assignment will work:
var x = function(){/* code */}()
Or array literal:
[function(){/* code */}()]
Or passing it as argument to a (cheap) function:
Object(function(){/* code */}())
Or applying a binary operator, provided the function expression is the second operand and not the first. Here with the comma operator:
0,function(){/* code */}()

Function is working when assigned to a variable but throwing SyntaxError when executed by itself

I had an IIFE like this one:
(function a() {
return "b";
}());
Executed in the console, it returns "b".
I removed the first set of parentheses, thinking that this'll make the "a" function global, but still work, and return "b":
function a() {
return "b";
}();
But it throws a SyntaxError:
Uncaught SyntaxError: Unexpected token )
Then, I tried converting the function to an expression by assigning to a variable, and it worked:
var c = function a() {
return "b";
}();
console.log(c); // prints b
Why does this happen? Why is it working as an expression but not by itself?
The second piece of code is not what it looks like.
This code looks like a function that is being immediately executed:
function a() {
return "b";
}()
But in reality, it's just a function declaration followed by an empty expression, which is not allowed:
function a() {
return "b";
}
() // not allowed - empty expression
Ben Alman explains this in his article on IIFE's:
When the parser encounters the function keyword in the global scope or
inside a function, it treats it as a function declaration (statement),
and not as a function expression, by default.
...
While parens placed after an expression indicate that the expression
is a function to be invoked, parens placed after a statement are
totally separate from the preceding statment, and are simply a
grouping operator (used as a means to control precedence of
evaluation).
The grouping operator needs to contain an expression to evaluate. By itself it's of no meaning:
() // meaningless
2 + 3 * 4 // 15
(2 + 3) * 4 // 20
In IIFE's, the outer parentheses are just a means of forcing the parser to expect an expression.
This is why the expression var c = function() { return "b"; }(); also works; it's because the parser knows to expect an expression because of the assignment to c.
Side Note
Alman also recommends against using self-invoking functions without using the outer parentheses when assigning to variables(i.e. var v = function(){...}()) because it's bad practice:
In cases where the extra “disambiguation” parens surrounding the
function expression are unnecessary (because the parser already
expects an expression), it’s still a good idea to use them when making
an assignment, as a matter of convention.
Such parens typically indicate that the function expression will be
immediately invoked, and the variable will contain the result of the
function, not the function itself. This can save someone reading your
code the trouble of having to scroll down to the bottom of what might
be a very long function expression to see if it has been invoked or
not.

add function received by ajax to object [duplicate]

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");

Purpose of the outer extra parenthese on JavaScript closure function [duplicate]

This question already has answers here:
JavaScript - self-executing anonymous functions and callback
(2 answers)
Closed 9 years ago.
What is the purpose of the outer extra parentheses on the below JavaScript closure function? I have been told in other posts that they are not strictly necessary, but they're a convention to make it clear that the result of the function is being passed, not the function itself. The below quote from http://www.adequatelygood.com/JavaScript-Module-Pattern-In-Depth.html
, however, conflicts. Which is correct?
Notice the () around the anonymous function. This is required by the
language, since statements that begin with the token function are
always considered to be function declarations. Including () creates a
function expression instead.
(function () {
// ... all vars and functions are in this scope only
// still maintains access to all globals
}());
I think that different engines have different ways of interpreting
function(){...}();
so the most popular and accepted way to make it clear, to all engines, is to group the code in parentheses.
(function(){...}());
At the same time, what you quoted makes a very interesting point. A function expression might go:
var f = function() {...}
Whereas a function declaration looks like:
function f() {...}
You see how it's easy/convenient for the parser to tell the difference by looking at the first token?
IF TOKEN1 EQ "function": FXN DECLARATION
ELSE: FXN EXPRESSION
But it wouldn't make sense for your (immediately-invoked) function to be a function declaration (it's not going to be re-used, you don't want to have it hoisted, or in the namespace, etc.) so adding some innocuous parentheses is a good way of indicating that it's a function expression.
First of all, I must clear up:
(function () {
}());
is equivalent for
(function () {
})();
and also for (Backbone.js uses it)
(function(){
}).call(this);
Second, if you're going to use it that way, then it's not an anonymous/closure function. its Immediately-Invoked Function expression
it would act as a closure (because it won't be immediately-invoked) if you assign its returned context to a variable. This kinda useful if you need a static class (when properties and methods could be accessed without instantiation). For example:
var stuff = (function(){
// AGAIN: its not an IIFE in this case
function foo() // <- public method
{
alert('Jeeez');
}
return {
foo : foo,
}
})();
stuff.foo(); //Alerts Jeeez
What is the purpose of the outer extra parentheses on the below
JavaScript closure function?
The purpose isn't usual and quite strange - its all about function arguments.
For example,
(function(window, document){ // <- you see this? 2 "arguments"
alert(arguments.length); // 0!
})();
but if we pass them to that outer parentheses
(function(/* So its not for arguments */ ){
alert(arguments.length); // 2
})(window, document); // <- Instead we pass arguments here
The extra surrounding parentheses disambiguate a function expression from a regular function declaration.
Though the extra parentheses are standard practice, the same thing can be achieved by doing this instead:
void function() {
// do stuff
}();
Or, even:
+function() {
// do stuff
}();
Though, out of these two alternatives, I prefer the void notation because in most cases we don't really care about the return value of an immediate invocation.
Other places where the parentheses aren't required is when an expression is expected:
setTimeout(function() {
return function() {
alert('hello');
}
}(), 1000);
They are necessary because the parser goes in the function declaration mode when it sees
function
in a statement context.
After function token, it is expecting a name for the function because a function declaration must include a name for the function. But instead of a name it sees ( instead, so it's a syntax error.
I think, it could backtrack and unambiguously just treat it as a function expression but it doesn't.
var module = XXX
In the above, XXX is in expression context, if a function appears there, it is treated as a start of a function expression. Function expressions don't have to have
a name for the function, so it's not a syntax error to have ( appear right after function.
So you can write:
var module = function(){}();
But not
function(){}()
You can use many tricks to make the above an expression:
(XXX)
!XXX
~XXX
+XXX
//This doesn't work however:
{YYY} //the braces are delimiting a block, and inside block you start in
//a statement context
XXX is in expression context because it's enclosed by parenthesis or is following a unary operator, therefore any function substituted for XXX is a function expression.

Syntax error on anonymous function declaration, but not after valid statement

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.

Categories

Resources