0

I'm new to JavaScript and am trying to learn JavaScript closures. I have two versions of the same code, the only difference is that version 2 has parentheses enclosing the function. I have run both versions and they seem to produce identical results. I was wondering if the parentheses enclosing "function incrementNumber()" are optional?

Version 1:

var incrementFunctionVariable = function incrementNumber(){
    var clickCount = 0;
    return function (){
        return ++clickCount;
    }
}()

Version 2: parentheses enclosing "function incrementNumber()"

var incrementFunctionVariable = (function incrementNumber(){
    var clickCount = 0;
    return function (){
        return ++clickCount;
    }
})()

<input type="button" value="click me" onclick="alert(incrementFunctionVariable())" /><br>
T.J. Crowder
  • 879,024
  • 165
  • 1,615
  • 1,639
Thor
  • 8,608
  • 10
  • 43
  • 113
  • 3
    They're optional *in that context*. If you wanted a standalone [IIFE](http://benalman.com/news/2010/11/immediately-invoked-function-expression/), i.e., if you didn't want to assign the return value to anything, you would need the parentheses (or a leading `!` or whatever). – nnnnnn Jul 01 '16 at 07:04
  • 1
    There has to be *some* kind of operator before the `function` keyword ... that's the difference between a `function declaration` and a `function expression`. The use of parens in *that* context are for the reader -- letting the human who reads the code know that it a IIFE.. and not a function to be called later. – Jeremy J Starcher Jul 01 '16 at 07:06
  • 2
    P.S. Note that this isn't really related to closures, because whether or not those parentheses are required is not related to what the function actually does or what it returns. – nnnnnn Jul 01 '16 at 07:15
  • 1
    Another note: In ES2015 `let` is an replacement for IIFEs, since it enables block scope. –  Jul 01 '16 at 07:21
  • 1
    @LUH3417: `let` is a replacement for **one small use case** of IIFEs. There are still plenty of others. – T.J. Crowder Jul 01 '16 at 07:28
  • 1
    Side note: English is clearly not your first language (though your English is very good!), so I'll just mention that "parentheses" is a plural (one parenthesis [note the 'is' at the end], two parentheses ["es" at the end]). So "*Are* the parentheses..." not "Is the parentheses..." (In fact, what few issues there were with the English in the question seemd to relate mostly to plurals and subject/verb agreement, just FWIW. And again, your English is really good. I guarantee you it's much better than I can do in your native language.) – T.J. Crowder Jul 01 '16 at 07:31
  • 1
    T.J. I disagree (partially). Scoping is the main purpose of IIFEs. What else do you mean? Private members? I don't use them. –  Jul 01 '16 at 07:40
  • 1
    @LUH3417: Let's say `let` combined with modules and inferred function names (once those are reliably in place on browsers) will largely do away with most use cases for IIFEs. :-) – T.J. Crowder Jul 01 '16 at 07:48
  • Just for clarification: Inferred function names mean that ES6 compliant engines can infer the name of an anonymous function from its lexical position, `const foo = function() {}; foo.name === "foo";` yields `true`. This works for normal assignments too. @T.J. agreed. –  Jul 01 '16 at 08:10
  • Indeed, that they *must* assign names to functions created via "anonymous" function expressions in a large number of situations where in ES5 the functions would be nameless. Anyone wanting to know more, search [the specification](http://www.ecma-international.org/ecma-262/6.0/index.html) (or [the new one](http://www.ecma-international.org/ecma-262/7.0/index.html)) for "SetFunctionName" to find those many and varied places. – T.J. Crowder Jul 01 '16 at 09:17

1 Answers1

3

This is very similar to JavaScript plus sign in front of function name, but perhaps not quite a duplicate.

In that particular case, you don't need the parentheses you're referring to, but you do in some other cases.

In JavaScript, if the parser is expecting a statement or declaration and it sees the function keyword, it assumes it's a function declaration (or in ES2015, a function statement). Those are not expressions (although in JavaScript, expressions are valid where statements/declarations are expected). Function declarations/statements don't produce a value you can immediately use in your code.

But if the parser is expecting an expression (for instance, on the right-hand side of an =), function starts a function expression. A function expression does produce a value (a reference to the function) you can use immediately in your code.

The reason you see () around function expressions is that people are used to writing them when they invoke the function immediately:

// WON'T WORK
function() { alert("foo"); }();

// Works
(function() { alert("foo"); }());

// Works
(function() { alert("foo"); })();

They do that to change the state of the parser from expecting a statement/declaration to expecting an expression, so that function starts a function expression, and so has a resulting value, which they can then use to call the function via ().

You don't need to do that in your example because after the =, the parser is already expecting an expression. But even though it's not necessary, it's commonly done, perhaps because it's really easy to read past the () at the end. That is, this:

var foo = function foo() {
    // lots of stuff here
};

and this

var foo = function foo() {
    // lots of stuff here
}();

are really easy to confuse. Adding the () to the latter makes them less similar:

var foo = (function foo() {
    // lots of stuff here
})();

But it's not necessary, if people do that, it's habit and/or style.

Community
  • 1
  • 1
T.J. Crowder
  • 879,024
  • 165
  • 1,615
  • 1,639