Javascript: rounded parentheses surrounding comma separated expressions - javascript

Playing on JS console I faced a curious syntax. I wonder if someone can tell me more on that..
Try this:
>( function f(){console.log('i am f')} , (function x(){console.log('i am x')})() , y=2 , console.log('hello') )
i am x
hello
undefined
>f()
ReferenceError: f is not defined
>this.y
2
This will fail:
( var c=2 )
SyntaxError: Unexpected token var
So comma separated expressions inside parentheses are evaluated, assignments happens to be against global scope, but named function declarations references stay trapped inside just like a closure
more...
putting that line inside a function declaration called with new:
function C(){
( function f(){console.log('i am f')} , (function x(){console.log('i am x')})() , y=2 , console.log('hello') )
}
and then instantiating:
>var c=new C()
i am x
hello
undefined
>c.y
undefined
>this.y
2
Happens exactly the same, just as executed in the global scope!
What's the usage / purpose of this construct?
One more:
>( function f(){console.log('i am f')} , f() )
ReferenceError: f is not defined
So the named function can't be referenced neither inside brackets.

The named functions aren't "trapped inside", because they're not function declarations (using function as a statement), they are in fact function expressions (using function as an operator). This means that their names do not become references to themselves in the current namespace.
Certain keyword/tokens can only be used as statements, such as var, hence an error is thrown if you try to use them in conditions which the interpreter expects to be an expression.
As for the y === 2, this is because you did not var y; inside C, so y = 2 sets window.y, and in the global scope this === window.
whats the usage / purpose of this construct?
The comma operator , lets you do multiple expressions on one line.
function expressions are useful for a great many things, be it immediately invoking them so you have a closure, or storing them inside variables, etc.

Wrapping code in parentheses forces it to be parsed as an expression.
The var keyword is only valid as a statement, so this creates a syntax error.
Function declarations can either be statements (which create a hoisted variable) or expressions (which do not create any variable).
Thus, wrapping the function in parentheses turns it into a function expression, which does not create an externally-visible name.
For more information, see here.

Related

Javascript are function in a module considered expresions or declarations

HI and thanks for taking the time. When you add a function as an accessible property of a module and expose it through the return statement. In other words, if you have an object and add a property such that "name:function(){return;}:" and expose that through the return statement of the module or object. is this an expression or a declaration? Once again thanks
I apologize I am not having a great day, no I am not taking a test but I described this incorrectly. When you export functions declared in a module, are they declarations or expressions? Thanks for your patience
A value part of an object literal, such as in a name: function(){return;} property, is an expression.
An expression is any valid set of literals, variables, operators and expressions that evaluates to a single value. We distinguish expressions to
Assignment Expressions - x = 7
Evaluation expressions - 3 + 4 - commonly written in curly brackets (x + y)
While what our goal behind these two expressions is different, it doesn't matter if they consist of 3 characters or a code that goes to 40 lines*, in the end, they all evaluate to a single decisive value, be it certain primitive value (number, string, boolean, null, undefined, symbol) or an object
Meanwhile, a declaration is well.. precisely as a name suggests.. a declaration of something
var x;
declares an undefined variable of name x
functions in javascript are simply sub-types of the object data type. So by doing
function foo (){} We simply declare an object (function) that to the top of the module.
Keep in mind, declaration and expressions do not have to be some sort of separate techniques that may never be combined, in fact, in real JS world it's quite the opposite:
var obj = {
foo: function bar() { console.log('baz'); }
};
Contains declaration of object obj. Assignment expression and declaration of function bar to the propety foo and also expression of the function bar itself.
Perhaps a much easier way to comprehend this would be:
var x = 7;
Where we first declare a variable x (var x) which is hoisted by the compiler to the top of our scope and then we assign it x = 7; but as a line by itself, it contains both a declaration and an expression

eval(fn) and eval(arrowFn) returns different value

As per the Mozilla docs in order to execute a function using eval it must be wrapped inside ( ) i.e. if you don't use them then it treated as a string.
eval as a string defining function requires "(" and ")" as prefix and suffix
when I execute normal function it returns undefined as expected but not in the case of ES6 functions. My Question is ES6 functions are treated differently by javascript engines or only within eval function.
var fn = "function a(){}";
var es6fn = "()=>{}";
console.log(eval(fn)); // undefined
console.log(eval(es6fn)); // ()=>{}
console.log(typeof eval(es6fn)); // ()=>{} i.e. a function
Lets take a step back and see what is actually going on here. I think you are misunderstanding the point MDN is trying to make. The only function that is executed in your example is eval. The (...) the documentation is mentioning are not for executing the function inside the string but for changing how the function definition is evaluated.
A function call would function a(){}() but the docs talk about putting the function definition inside parenthesis: (function(){}).
There are basically thee major ways to define functions:
Function declaration
function foo() {}
Function expression
var foo = function() {}
Arrow function
var foo = () => {}
To understand the difference between a function declaration and a function expression, we have to understand the difference between statements and expressions (a declaration is basically like a statement).
A statement is something that has side effects and does not produce a value. if, for, switch, etc are all statements.
An expression is something that produces a value. E.g. 5 is a number literal that produces the value 5. 5 + 3 is an expression that computes the sum of the two literals, i.e. evaluating it will return the value 8.
A function declaration is like a statement. It doesn't produce a value itself, but as a side effect, a variable is defined whose value is a function (you can see in the specification that nothing happens when a function declaration is evaluated (they have already been processed at that point)).
A function expression is very similar, but instead of defining a variable, evaluating it simply results in the function object.
And that is the reason why
eval('function a() {}') // undefined, but a is defined as side effect
eval('(function a() {})') // a function object
produce different results. The first is interpreted as function declaration. A variable a will be created, but no value is created that eval could return. In the second case, the grouping operator ((...)) forces the function definition to be interpreted as a function expression, which means that a value is produced and return by eval.
Now regarding arrow functions: There is no ambiguity here. Arrow function definitions are always expressions, i.e. evaluating them always produces a value.
eval(`() => {}`) // a function object
To sum up
While there is a difference between arrow functions and function declarations/expressions, this difference is not the reason for the results you are seeing with eval. The difference here is because of evaling a statement/declaration and an expression.
In your example, a is declared as it's a named function. In the second case, you just write an expression which is a lambda function. See here and here.
If you want to get the same effect for fn, do
`console.log(eval("var a = function(){}"))`; //`function(){}`.
First of all, EcmaScript is the "official" name for JavaScript. Now that ES2015 is finalised, it effectively just becomes JavaScript v6 to most people. So, this difference does not come from the different engin.
The origin of the different behavior comes from the result of the string which is written in the eval function. the result of the first eval string is a function definition and there is not anything to return. On the other side, the second eval is evaluating a lambda function, so the result of the eval is that function. To clear this concept, you can rewrite the code like the following:
var fn = "function a(){ return 1;}";
var es6fn = "()=>{}";
console.log(eval(fn)); // undefined
console.log(eval(es6fn)); // ()=>{}
console.log(typeof eval(es6fn)); // ()=>{} i.e. a function
console.log(a()); // call the a() function
As, you can see, the a() is defined as a function, and you can use the function after the first eval. So, the first eval is run and all back to the return value for eval function.
The documentation says nothing on function execution. The functions won't be executed, unless they are executed explicitly like (() => {})().
The quote
eval as a string defining function requires "(" and ")" as prefix and suffix
refers to interpreting the string as function expression rather than function declaration.
// will throw SyntaxError
// because function declaration requires a name
typeof eval('function (){}');
typeof eval('function a(){}') === 'undefined';
typeof eval('(function a(){})') === 'function';
typeof eval('null, function a(){}') === 'function';
typeof eval('()=>{}') === 'function';
Arrow function is always an expression, it doesn't need auxiliary constructions like comma or parentheses to interpret is an expression, here is the difference.

Why are parentheses required around JavaScript IIFE? [duplicate]

This question already has answers here:
Explain the encapsulated anonymous function syntax
(10 answers)
Closed 7 years ago.
I'm reading up on JavaScript IIFE and so far the understand concept, but I am wondering about the outside parenthesis. Specifically, why are they required? For example,
(function() {var msg='I love JavaScript'; console.log(msg);}());
works great, but
function() {var msg='I love JavaScript'; console.log(msg);}();
generates a syntax error. Why? There are lots of discussions on IIFE, but I'm not seeing a clear explanation about why the parentheses are required.
There are two ways to create functions in JavaScript (well, 3, but let's ignore new Function()). You can either write a function declaration or write a function expression.
A function declaration in itself is a statement and statements by themselves don't return values (let's also ignore how the debugging console or Node.js REPL print return values of statements). A function expression however is a proper expression and expressions in JavaScript returns values that can be immediately used.
Now, you may have seen people saying that the following is a function expression:
var x = function () {};
It may be tempting to conclude that the syntax:
function () {};
is what makes it an expression. But that's wrong. The syntax above is what makes it an anonymous function. And anonymous functions can either be a declaration or an expression. What makes it an expression is this syntax:
var x = ...
That is, everything to the right of an = sign is an expression. Expressions make it easier to write math formulas in programming languages. So in general everywhere that math is expected to be processed is an expression.
Some of the forms of expressions in JavaScript include:
everything to the right of an = operator
things in braces () that are not function call braces
everything to the right of a math operator (+,-,*,/)
all the arguments to the ternary operator .. ? .. : ..
When you write:
function () {}
it is a declaration and does not return a value (the declared function). Therefore trying to call the non-result is an error.
But when you write:
(function () {})
it is an expression and returns a value (the declared function) which may be used immediately (for example, may be called or may be assigned).
Note the rules for what counts as expressions above. From that it follows that braces are not the only things that you can use to construct an IIFE. Below are valid ways for constructing IIFEs (because we write function expressions):
tmp=function(){}()
+function(){}()
-function(){}()
0/function(){}()
0*function(){}()
0?0:function(){}()
(function(){}())
(function(){})()
You may actually see one of the above non-standard forms (particularly the + version) in third-party libraries, because they want to save one byte. But I strongly advise you to only use the brace forms (either are fine), because they are widely recognized as IIFEs by other programmers.
The version of IIFE that is wrapped in parenthesis works, because this marks the declaration of the internal function declaration as an expression.
http://benalman.com/news/2010/11/immediately-invoked-function-expression/
For more detailed explanation please see:
Advanced JavaScript: Why is this function wrapped in parentheses?
HINT:
The invocation operator (()) only works with expressions, not declarations.
This will be a long-winded answer, but will give you the necessary background. In JavaScript there are two ways functions can be defined:
A function definition (the classical kind)
function foo() {
//why do we always use
}
and then the more obscure type, a function expression
var bar = function() {
//foo and bar
};
In essence the same thing is going on at execution. A function object is created, memory is allocated, and an identifier is bound to the function. The difference is in the syntax. The former is itself a statement which declares a new function, the latter is an expression.
The function expression gives us the ability to insert a function any place where a normal expression would be expected. This lends its way to anonymous functions and callbacks. Take for instance
setTimeout(500, function() {
//for examples
});
Here, the anonymous function will execute whenever setTimeout says so. If we want to execute a function expression immediately, however, we need to ensure the syntax is recognizable as an expression, otherwise we have ambiguity as to whether of not we mean a function expression or statement.
var fourteen = function sumOfSquares() {
var value = 0;
for (var i = 0; i < 4; i++)
value += i * i;
return value;
}();
Here sumOfSquares is immediately invoked because it can be recognized as an expression. fourteen becomes 14 and sumOfSquares is garbage-collected. In your example, the grouping operator () coerces its content into an expression, therefore the function is an expression and can be called immediately as such.
One important thing to note about the difference between my first foo and bar example though is hoisting. If you don't know what that it is, a quick Google search or two should tell you, but the quick and dirty definition is that hoisting is JavaScript's behavior to bring declarations (variables and functions) to the top of a scope. These declarations usually only hoist the identifier but not its initialized value, so the entire scope will be able to see the variable/function before it is assigned a value.
With function definitions this is not the case, here the entire declaration is hoisted and will be visible throughout the containing scope.
console.log("lose your " + function() {
fiz(); //will execute fiz
buzz(); //throws TypeError
function fiz() {
console.log("lose your scoping,");
}
var buzz = function() {
console.log("and win forever");
};
return "sanity";
}()); //prints "lose your scoping, lose your sanity"

Is a function hoisted if it is defined within an if condition?

So suppose I have something like this
var x = 1;
if (function f(){}) {
x += typeof f;
}
x;
This outputs "1undefined". I thought it should have output "1function", because function f(){} should have been hoisted above the if. This is clearly not the case - why? I thought function declarations and bodies were always hoisted to the top of the scope?
Function declarations are hoisted. Function expressions are not.
This creates a named function expression:
if(function f(){})
It doesn't do anything except check to see if the function expression is truthy. (Function expressions are always truthy.)
Regarding named function expressions, see https://kangax.github.io/nfe/#named-expr:
An important detail to remember is that this name is only available in
the scope of a newly-defined function
This code is outside the scope of the new function expression, and therefore f is undefined:
x += typeof f;
Within a named function expression, you can refer to its name without a problem:
(function f() {
alert(typeof f); //function
})();
alert(typeof f); //undefined
As far as I know ES5 does not define the behavior for function declarations inside blocks.
Quoting Kangax:
FunctionDeclarations are only allowed to appear in Program or
FunctionBody. Syntactically, they can not appear in Block ({ ... }) —
such as that of if, while or for statements. This is because Blocks
can only contain Statements, not SourceElements, which
FunctionDeclaration is. If we look at production rules carefully, we
can see that the only way Expression is allowed directly within Block
is when it is part of ExpressionStatement. However,
ExpressionStatement is explicitly defined to not begin with "function"
keyword, and this is exactly why FunctionDeclaration cannot appear
directly within a Statement or Block (note that Block is merely a list
of Statements).
Because of these restrictions, whenever function appears directly in a
block (such as in the previous example) it should actually be
considered a syntax error, not function declaration or expression. The
problem is that almost none of the implementations I've seen parse
these functions strictly per rules (exceptions are BESEN and
DMDScript). They interpret them in proprietary ways instead.
Function declarations are statements. The conditional part of an if-statement is an expression, so what you have is a function expression; it cannot be a function declaration. And so it isn't hoisted, since only function declarations are.

Self-executing function syntax and callback syntax explained

bit of a silly question perhaps.
But I want to understand why the syntax on the self-executing function and the callback it has is so different to all the other JS syntax..
(function () {
})()
I just need to understand why its valid to encapsulate it with () I wouldn't have guessed that to be valid, and then the extra () afterwards for the callback, (which just sits directly after it, I also wouldn't have expected that to be valid.
Is anyone able to explain this to me?
The function (...) {...} part is a function expression, that is, an expression that represents a function. The only reason it has to be wrapped in parentheses in this case is that if the keyword function is the very first thing in a statement, then the statement is assumed to be a function statement, that is, a function declaration. (Actually, it doesn't necessarily have to be wrapped in parentheses; it also works to prefix it with a +, or in general to put any sort of token before function that prevents the function-statement interpretation.)
The () part after the function expression is the same as the normal () for calling a function. This:
(function (...) {...})(...);
is (aside from the temporary variable) the same as this:
var f = function (...) {...};
f();
which is equivalent to this:
function f(...) {...};
f();
Essentially the outer parentheses allow the function object to be fully interpreted and instantiated, so that once you exit the scope of those parentheses the function object is ready to be called.
See here:
Why do you need to invoke an anonymous function on the same line?
When declaring as you did, you are using it as a function expression (3rd way of defining the function from the above link). As with any expression, this (expression) evaluates to expression - parentheses are used here is establish precedence where necessary. So you can write this for example:
var f = function(a) {
var s = (((( 1 )))) + (((( a ))));
console.log(s);
};
((((( f ))))) (2);
(live example) and then remove all the unnecessary parentheses with the same result (which is printing of 1 + 2 = 3, essentially). The result of:
(function(...) { ... })
is a function that accepts some arguments and has a body to be executed. This:
(function(...) { ... })()
is pretty much equivalent to:
var f = (function(...) { ... });
// Now f is a function that can be called
f();
Anonymous functions are useful, among other things, for two reasons - they are anonymous (i.e. they don't create additional names - see again the above SOq link) and they are "containers" for other stuff that doesn't need to be global.
What you have here is an Immediately-invoked function expression also known as IFFE (read iffy) and is a design pattern which produces lexical scope using JS function scoping. These are used to avoid variable hoisting, polluting the global environment and simultaneously allowing public acces to methods while retaining the local privacy of variables declared whithin the function.
The key to understanding this is that JS has function scope and not block scope and passes values by reference inside a closure.
You can read further into this at Immediately-invoked function expression.

Categories