Reputation: 10798
What do you call these patterns? What is the difference between them? When would you use each? Are there any other similar patterns?
(function() {
console.log(this); // window
})();
(function x() {
console.log(this); // window
})();
var y = (function() {
console.log(this); // window
})();
var z = function() {
console.log(this); // window
}();
EDIT: I just found two more seemingly redundant ways to do this by naming the functions in the last two cases...
var a = (function foo() {
console.log(this); // window
})();
var b = function bar() {
console.log(this);
}();
EDIT2: Here is another pattern provided below by @GraceShao which makes the function accessible outside the function scope.
(x = function () {
console.log(this); // window
console.log(x); // function x() {}
})();
console.log(x); // function x() {}
// I played with this as well
// by naming the inside function
// and got the following:
(foo = function bar() {
console.log(this); // window
console.log(foo); // function bar() {}
console.log(bar); // function bar() {}
})();
console.log(foo); // function bar() {}
console.log(bar); // undefined
Upvotes: 14
Views: 9931
Reputation: 49271
JavaScript in the browser is the lacks namespacing. Every piece of code runs in the global scope; therefore, internal application code or third-party dependencies can pollute the scope while exposing their own pieces of functionality. Polluting global namespace causes name collision. This name collision is very common in large projects and can be extremely harmful.
Imagine, for instance, that a third-party library instantiates a global variable called utils. If any other library, or the application code itself, accidentally overrides or alters utils, the code that relies on it will likely crash in some unpredictable way. Unpredictable side effects can also happen if other libraries or the application code accidentally invoke a function of another library meant for internal use only.
(function () {
// create state variables
// make some operation
// then return those
const export = {
export1: () => {},
export2: () => {}
}
return exported
})()
it is used to create a private scope, exporting only the parts that are meant to be public.
Why do we even need those? The reason is purely syntactical. The JavaScript parser has to be able to easily differentiate between function declarations and function expressions. If we leave out the parentheses around the function expression, and put our immediate call as a separate statement
function(){}(3)
, the JavaScript parser will start processing it, and will conclude, because it’s a separate statement starting with the keyword function, that it’s dealing with a function declaration. Because every function declaration has to have a name (and here we didn’t specify one), an error will be thrown. To avoid this, we place the function expression within parentheses, signaling to the JavaScript parser that it’s dealing with an expression, and not a statement.
You might also see this in some projects:
+function(){}();
-function(){}();
!function(){}();
~function(){}();
This time, instead of using parentheses around the function expressions to differentiate them from function declarations, we can use unary operators: + , - , ! , and ~
. We do this
to signal to the JavaScript engine that it’s dealing with expressions and not statements.
Upvotes: 0
Reputation: 141829
Here are your functions again with some comments describing when/why they might be useful:
(function() {
// Create a new scope to avoid exposing
// variables that don't need to be
// This function is executed once immediately
})();
(function fact(i) {
// This named immediately invoked function
// is a nice way to start off recursion
return i <= 1 ? 1 : i*fact(i - 1);
})(10);
var y = (function() {
// Same as the first one, but the return value
// of this function is assigned to y
return "y's value";
})();
var z = function() {
/* This is the exact same thing as above
(except it is assigned to z instead of y, of course).
The parenthesis in the above example don't do anything
since this is already an expression
*/
}();
Upvotes: 39
Reputation: 1779
It's time to use ES06, Here are your functions using arrow function from ES06.
(() => {
// Create a new scope to avoid exposing variables that don't need to be
// This function is executed once immediately
})();
(fact = (i)=>(
// This named immediately invoked function is a nice way to start off recursion
i <= 1 ? 1 : i*fact(i - 1)
))(10)
const y = (() => (
// Same as the first one, but the return value of this function is assigned to y
"y's value"
))();
const z = (() => {
// This is the exact same thing as above (except it's assigned to z instead of y, of course).
// The parenthesis in the above example don't do anything since this is already an expression
})();
Upvotes: 0
Reputation: 1
(function() { 'use strict'; you can use this type
Why?: An IIFE-Immediately Invoked Function Expression removes variables from the global scope. This helps prevent variables and function declarations from living longer than expected in the global scope, which also helps avoid variable collisions.
Why?: When your code is minified and bundled into a single file for deployment to a production server, you could have collisions of variables and many global variables. An IIFE protects you against both of these by providing variable scope for each file.
Upvotes: 0
Reputation:
In this case they are all semantically identical. The ECMAScript specification contains the full production rules, so this is a gross simplification.
Also note that I am ignoring the named function's name (x
) as the name is not used; it could be referenced within the body but since it is a FunctionExpression (via the grammar production) it would never (in a correct JS implementation) contaminate the containing scope - see the comments.
(function() {
console.log(this); // window
})();
(function x() {
console.log(this); // window
})();
var y = (function() {
console.log(this); // window
})();
var z = function() {
console.log(this); // window
}();
Reduced (the bodies are inconsequential in this case, they all "return undefined"):
(function() {})();
(function x() {})();
var y = (function() {})();
var z = function() {}();
Reduced (in the ECMAScript grammar FunctionExpression
is a production rule, but here I use it to mean "an expression that is a function"):
FunctionExpression()
FunctionExpression()
var y = FunctionExpression()
var z = FunctionExpression()
Ignoring the assignment of the result (which would always be undefined
) it can be seen that all forms are the same.
Happy coding.
Upvotes: 6
Reputation: 5679
Self invoking anonymous function. The function body will be invoked immediately.
(function() {
console.log(this); // window
})();
Self invoking function. The function body will be invoked immediately. You can still refer to the function x
inside the function body. So when you want to execute something immediately, and then you may want to iterate it, you can just reference to it directly.
(function x() {
console.log(this); // window
console.log(x); // function x() {}
})();
The self invoking anonymous function on the right side will be invoked immediately, and the returned value will be assigned to the y
. Usually it has a return value when you use this pattern, otherwise, y will be undefined
.
var y = (function() {
console.log(this); // window
})();
IMO, it is same as the third one. The parentheses of the 3rd enclosing the function are just for making the function look like one entire thing. But the functionalities of the both are the same.
var z = function() {
console.log(this); // window
}();
Similar to the 2nd one, but you can reference the x outside the function scope by using:
(x = function () {
console.log(this); // window
console.log(x); // function x() {}
})();
console.log(x); // function x() {}
Upvotes: 2