I've been programming in JS since some time, but I have never came upon a need of using immediate functions, for example:
(function(){
console.log('hello, I am an immediate function');
}())
What would be the difference if I just wrote:
console.log('hello, I am an immediate function');
? I don't have any access to this function anyway (it is not assigned anywhere). I think (but I'm not sure) that I can implement everything without immediate functions - so why do people use it?
-
2google "Javascript Self Invoking Functions", you have a few things to read, and everything should get clear after...AntouanK– AntouanK2013年06月20日 11:35:57 +00:00Commented Jun 20, 2013 at 11:35
-
1Well, in your case there really is no difference (other than the call stack and the slower execution). But no, not everything can be done without them.Bergi– Bergi2013年06月20日 11:43:59 +00:00Commented Jun 20, 2013 at 11:43
-
Just a FYI that this question is one of the first search hits in a google query for "Node js immediate function", which is even a auto-completion suggestion from Google. It's very bad that this question is marked as duplicate of a post that's largely unrelated, at least to those who arrive here while looking into Node.js's event loop.RAM– RAM2021年10月19日 11:36:21 +00:00Commented Oct 19, 2021 at 11:36
6 Answers 6
Update:
I've found this question where I did go into more details on closures, comlete with little drawings to clarify how closures, and function scopes are used (and how they can help you).
IIFE's, being function objects, are the only way to create real scopes in JS. They're used all over the place. Have you ever used jQuery, or some other lib? then you've used code that uses IIFE's.
Ever looked into node.js? Then you might have come across something called "the module pattern".
If you've had a go at writing your own constructor, you've probably wondered how you could have some sort of private property onto an object. The answer is IIFE's time and time again.
Also: The DOM api isn't the fastest thing in the world. Having a function containing a hard-coded document.getElementById call means that, every time the function gets called, the DOM will be traversed. That's not ideal. A quick, and easy way to fix this issue would be this:
var f = (function(domReference)
{
var visible = !!(domReference.style.visibility === 'block')
return function()
{//has access to vars and arguments of outer function
domReference.style.visibility = visible ? 'none' : 'block';
visible = !visible;
}
}(document.getElementById('foobar'));
But perhaps the best, and most common example is timeouts/intervals in loops:
for (var i=0;i<10;i++)
{
setTimeout((function(currentI)
{
return function()
{
console.log(currentI);
console.log(i);
}
}(i)), 1000);
Here, currentI will log 0, 1, 2... and so on, whereas i will always log 10. The reason being the timeout callback doesn't get its own copy of i's value, but it references the variable i. That variable can change its value as much as it wants, when the timeout callback is invoked, it'll log whatever value i was last assigned. Not the value i was assigned when the callback was defined.
Without going into too much detail, I mentioned private properties for objects. Well, here's an example for you to work out why the IIFE's and function scopes are crucial, and an incredibly powerful feater of JS:
var MyConstructor = (function()
{
return function(foo, bar)
{
var initState = Array.prototype.slice.apply(arguments, [0]);
this.getInit = function()
{
return initState;
};
this.foo = foo;
this.bar = bar;
}
}());
(function(constant)
{
var F = function(args)
{
return MyConstructor.apply(this, args);
},
checkVar = constant || 'default constant value';
F.prototype = MyConstructor.prototype;
MyConstructor.prototype.getConstant = function()
{
if (constant !== checkVar)
{//bad example
return checkVar;
}
return constant;
};
MyConstructor.prototype.regularMethod = function()
{
return this.foo;
};
MyConstructor.prototype.copyFromInitState = function()
{
return new F(this.getInit());
};
}('Immutable value'));
Have fun working this out... :P
4 Comments
let variables or block scope. Some people use object literals, and delete temporary values to have some sort of "scope object"Immediately invoked function expressions are used to create namespaces. I won't explain precisely why an IIFE is so important - Ben Alman does a mighty good job at that. Nevertheless, I will say that one of the most important uses of an IIFE is to create closures. Consider:
var counter = (function () {
var count = 0;
return function () {
return ++count;
};
}());
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3
The reason we use an IIFE is because JavaScript doesn't have block scoping. Hence a IIFE is used to simulate a block scope. JavaScript 1.7 introduced the let keyword which allows you to create block scoped variables. However most implementations don't support let hence we still use IIFEs.
For example the above program could be rewritten using the let keyword as follows:
var counter;
{
let count = 0;
counter = function () {
++count;
};
}
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3
Also notice that an IIFE can return values. Normal blocks can't do that. Hence you need to manually assign the return value to a global variable.
Mostly however an IIFE is used to encapsulate the private state of a library. It's considered bad practice to create a bunch of globals.
Sometimes it's used to encapsulate logically similar elements because as humans we like to group things. It may not really make a difference but organizing code is good. For instance, consider:
function Pet(name) {
this.name = name;
}
Pet.prototype.feed = function (food) {
console.log(this.name + " is eating " + food + ".");
};
Instead of this it just looks better to encapsulate your code as follows:
var Pet = (function () {
function Pet(name) {
this.name = name;
}
Pet.prototype.feed = function (food) {
console.log(this.name + " is eating " + food + ".");
};
return Pet;
}());
Oh, most important. An IIFE is also used to solve the Javascript infamous Loop issue?
2 Comments
let is a future reserved keyword and will not be added until ES6. Chrome only supports it as an experimental feature, and it was introduced by Mozilla as part of their own superset of JSPeople use it because its one of the most powerful features in javascript. Have a read and welcome to Javascript. http://javascript.crockford.com/private.html
Comments
Developers use Immediate Functions to declare private scopes. For instance...
(function($){
$("div").html("example");
})(jQuery);
With this code you don't need $ variable in the global scope, just window.jQuery outside. It prevents posible conflicts when you want to use variable names that another libraries are using in the window object (for instance, you could be using window.$ for another proposes, like Prototype.js).
Comments
self-invoking functions are used to prevent global variable collision. For example:
(function($){
//your code
})(jQuery);
In the above example, if it is in a page using jQuery and Prototype.js, you may safely refer to $ object and know that it is jquery's $ object not prototype's $ object.
2 Comments
bar = 'foo' in your IIFE, I'd still be cluttering the global scope (implied globals)The reason why people use it is emulation of private scopes. Any variable defined in anonymous function body will be hidden from outer scope (usually it's window and trash window with temp variables is bad idea).