How does JavaScript's grouping operator work?

When function is at the beginning of a statement, it's treated as the beginning of a named function definition, which should be like:

function someName() { return 1; }

This is a statement, not an expression, so it can't be used as part of a larger expression.

In fact, it's not valid to have that statement without a name. You get a syntax error from:

function() { return 1}

all by itself.

But when you put it after a parenthesis, it's not the beginning of a statement any more, so it's a function expression, which returns the function as a value. Then it can be used as a sub-expression in a larger expression.

It's not the grouping operator that does it, just the fact that it's not at the beginning of the statement. For instance, you can also write:

var foo = function() { return 1 } + "text";

The 1+2; is something that works in most languages with a C-inspired syntax. One of the kinds of allowed statements in Javascript is a statement that just contains an expression. This is to allow statements that just contain a function call, such as foo(); or assignment statements like x=5;. Yes, assignments in Javascript are considered expressions instead of statements, which is why you are allowed to shoot yourself in the foot and put an assignment inside an if-statement conditional (the classic = vs == bug). In the end, it would be hard for the compiler to forbid useless expression-statements such as 1+2; while still allowing foo() and x = 5;.

The function(){} vs (function(){}) thing is a Javascript quirk. Javascript has different rules in the grammar for "function declaration statements" and "function expressions". In the first example the function is parsed as a statement, which cannot be added to other things. In the second, the parenthesis makes the function be parsed as an expression, which allows it to be added to other things.

This is why the "self invoking function pattern" always adds a pair of parenthesis arounf the anonymous function.

(function(){
     ...
 }())

The question is about the grouping operator (), or precedence operator.

Preliminary note: parenthesis used in "function [name](){}" are part of the syntax of the function (idem for function invokation), not a grouping operator.

The grouping operator has the highest precedence over any other operator, precisely because its role is to alter the precedence of the expression contained in it (i.e. in parenthesis). This means that the expression within parenthesis is fully evaluated before its value is used in the remainder of the expression. Henceforth:

(1+2); // strictly equivalent to 1+2;
       // because nothing more in the expression

or:

var x = ("3"==3)? "ok":"ko"; // grouping operator is useless as well

... but (as stated in Barmar'answer): the syntax "function(){return 1;}", when put between (), is operated by the grouping operator, and is considered as an expression to be executed before being used in the full statement, and there are 2 consequences:

  1. an anonymous function is allowed, for we are in a function expression;
  2. to be executed, a function expression must have arguments provided to its parameters, and -if you are expecting the return value(note2)- a second pair of parenthesis is mandatory, to contain the arguments, or no argument. (function(){return 1;}());

Note2: the original question was mentioning the example:

(function(){return 1} + "text");  //-> function(){return 1}text

as not returning a Syntax Error: it's correct, but it returns the code of the function as a string value, not the value 1, followed by the string 'text'. Why? because no parenthesis were provided for the execution. We should rather write:

(function(){return 1}()) + "text"; //-> 1text

Tags:

Javascript