2

Can anyone explain me the following function inside a JS file

function Init() { (function set() { -----code--- print "hello"; } )(); } 

If I call the function Init , does it automatically run the function set as well or i need to call set() to run it?

2
  • Yes, because its an IIFE that defines a scope around your code. In your case it can make no difference because Init already created a scope. Commented Jan 23, 2017 at 20:05
  • This question is similar to: What is the (function() { } )() construct in JavaScript?. If you believe it’s different, please edit the question, make it clear how it’s different and/or how the answers on that question are not helpful for your problem. Commented Apr 20 at 15:24

4 Answers 4

1

You need to call Init to run any code inside of it. Now, that code inside is just regular JavaScript code, but an interesting one. Let's see why.


How

Your inner function is a so-called IIFE. What you can do to make it easier to read the outer function (Init), is to replace the inner function with the result of the IIFE call.

Here are a few examples:

var x = undefined; // x === undefined x = (undefined); // again x = 3; // x === 3 x = (3); // again the same x = 'some string'; // some string x = ('some string'); // the same 

So it's ok to put () around an object, you get the same object. The same for a function

x = function() {}; // x is that function now. x = (function() {}); // the same. 

But if you say x = 3;, can you call x?

x = 3; x(); // syntax error x = (3); x(); // again error. can't call a number. 

But, if your x is a function, you can call it:

x = function() { console.log('Hi'); }; // you can call x now. x(); // logs 'Hi'! 

So if you do the same with parenthesis, it's the same:

x = (function() { console.log('Hi'); }); // again, the same. x(); // no error, function called again! 

So you can skip the assignment part:

// instead of x = (...); and the x(), you replace the x part right away. (function() { console.log('Hi'); })() // function body up to here ^^ now the call part. 

Note that it won't work without the first pair of parens:

function() { console.log('Hi'); }(); // syntax error. 

So you're putting the outer parens () just to cast that function expression into an object in-place.


Why

So that's how it works. But why? Because you wanna make sure nobody else calls your function! If you do this:

var x = function() {}; x(); 

Now there are at least two things that can happen that you might not want:

  1. There might be a name clash. You might not know if there's an "x" already defined on wherever the outer function is gonna be called at, e.g. you bind Init to some object which has x at scope or something.

  2. Somebody can "steal" your x and call it again. Not necessarily steal, you just leak it (a subtle bug) and some other code calls x, expecting to find its own x, but in fact, it's your x now because it is reachable. And you wanted it not to be.

So you handily lock it away in anonymous function that's executed right away.

Hope this clears things a bit.

Sign up to request clarification or add additional context in comments.

3 Comments

"So you're putting the outer parens () just to cast that function def into an object in-place.". Actually, the outer parenthesis changes what might be a function declaration into a function expression. Any punctuator can be used that is allowed at the start of a statement, e.g. +, - or ! as in !function(){}(). ;-)
@RobG Awesome! TIL !function() { console.log('a'); }() twitter.com/zladuric/status/823632051572248577
Yep, saves one character over (function(){}()). ;-)
0

When you do

(function set() { /*code here*/ })(); 

, it is a close equivalent to

var set = function () { /*code here*/ }; set(); 

So when you call Init(), the set function will be called.

4 Comments

I'd say it's not technically equal. In the first example, there are no objects left at the current scope after the call. In the second example, you have a set variable in the code above and bellow the call (and it's not even undefined bellow).
@Zlatko In the first example, there are no objects left at the current scope That's false. In the first example, you can call set() anywhere within the function Init and it will work, as opposed to the second where you can only call set() after the assignment. Even in the case of an anonymous function, an internal name was created for it within the environment of the Init's scope and that before it even started to interprete the first line of the function Init.
nope, set is not available in the outer function scope or anywhere outside set itself. Check this out: gist.github.com/zladuric/dae9dc89297921f4f4023dee53e667fd Or did I understand you incorectly?
@Zlatko I was wrong. I found the reference in the spec: ... unlike in a FunctionDeclaration, the Identifier in a FunctionExpression cannot be referenced from and does not affect the scope enclosing the FunctionExpression.
0

You would need to call Init(); to execute the function.

The (function () {console.log('IIFE') }());

Syntax you are referring to is an immediately-invoked function expression.

1 Comment

there is a typo still
0

this is a basic function closure in js (an inner function inside another one).

also.. it is anonymous function..meaning...you can only use that function once (and that is why the function call is attached to function deceleration). so...

function regular() { function regular_closure() { } (function () // this is anonymous { })(); // call the anonymous function.. which is also a closure regular_closure(); // call the function } 

more about this topic:

MDN - js closures in depth

When to use js closure

4 Comments

I think calling this a closure is misleading. Every function has a closure the variables in its outer execution contexts, not just immediately invoked functions. The function is executed every time regular is called, so not really only used once and it's a function expression, not a declaration.
Yep, this is a closure, but I think the question doesn't touch on closure per se. There's nothing accessed from the closure so it's not so relevant.
that is actually why i attached the link from MDN :)
The link is to closure. Closure is not a relevant part of it, I would say, and I think @RobG would agree?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.