-
Notifications
You must be signed in to change notification settings - Fork 22.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
improve IIFE docs #37361
improve IIFE docs #37361
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,155 +6,43 @@ page-type: glossary-definition | |
|
||
{{GlossarySidebar}} | ||
|
||
An **IIFE** (Immediately Invoked Function Expression) is a {{glossary("JavaScript")}} {{glossary("function")}} that runs as soon as it is defined. | ||
The name IIFE is promoted by Ben Alman in [his blog](https://web.archive.org/web/20171201033208/http://benalman.com/news/2010/11/immediately-invoked-function-expression/#iife). | ||
An **IIFE** (Immediately Invoked Function Expression) is an idiom in which a {{glossary("JavaScript")}} {{glossary("function")}} runs as soon as it is defined. It is also known as a _self-executing anonymous function_. The name IIFE is promoted by Ben Alman in [his blog](https://web.archive.org/web/20171201033208/http://benalman.com/news/2010/11/immediately-invoked-function-expression/#iife). | ||
|
||
```js | ||
// standard IIFE | ||
(function () { | ||
// … | ||
// statements… | ||
})(); | ||
|
||
// arrow function variant | ||
(() => { | ||
// … | ||
// statements… | ||
})(); | ||
|
||
// async IIFE | ||
(async () => { | ||
// … | ||
// statements… | ||
})(); | ||
``` | ||
|
||
It is a design pattern which is also known as a {{glossary("Self-Executing Anonymous Function")}} and contains two major parts: | ||
It contains two major parts: | ||
|
||
1. The first is the anonymous function with lexical scope enclosed within the [grouping operator](/en-US/docs/Web/JavaScript/Reference/Operators/Grouping) `()`. This prevents accessing variables within the IIFE idiom as well as polluting the global scope. | ||
2. The second part creates the immediately invoked function expression `()` through which the JavaScript engine will directly interpret the function. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this was particularly incomprehensible to me There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed since it doesn't have to be
|
||
1. A [function _expression_](/en-US/docs/Web/JavaScript/Reference/Operators/function). This usually needs to be [enclosed in parentheses](/en-US/docs/Web/JavaScript/Reference/Operators/Grouping) in order to be parsed correctly. | ||
2. Immediately _calling_ the function expression. Arguments may be provided, though IIFEs without arguments are more common. | ||
|
||
## Use cases | ||
IIFEs are a common pattern used to execute arbitrarily many statements in their own scope (and possibly return a value), in a location that requires a single expression. They are similar to, but much more powerful than, the [comma operator](/en-US/docs/Web/JavaScript/Reference/Operators/Comma_operator), which can only execute multiple expressions and, therefore, does not provide a way to use local variables or control flow statements. | ||
|
||
### Avoid polluting the global namespace | ||
Use cases of IIFEs include: | ||
|
||
Because our application could include many functions and global variables from different source files, it's | ||
important to limit the number of global variables. If we have some initiation code that we don't need to use | ||
again, we could use the IIFE pattern. As we will not reuse the code again, using IIFE in this case is better than | ||
using a function declaration or a function expression. | ||
- Avoiding polluting the global namespace by creating a new {{glossary("scope")}}). | ||
- Creating a new async context to use {{jsxref("Operators/await", "await")}} in a non-async context. | ||
- Computing values with complex logic, such as using multiple statements as a single expression. | ||
|
||
```js | ||
(() => { | ||
// some initiation code | ||
let firstVariable; | ||
let secondVariable; | ||
})(); | ||
|
||
// firstVariable and secondVariable will be discarded after the function is executed. | ||
``` | ||
|
||
### Execute an async function | ||
|
||
An [`async`](/en-US/docs/Web/JavaScript/Reference/Operators/async_function) IIFE allows you to use [`await`](/en-US/docs/Web/JavaScript/Reference/Operators/await) and [`for-await`](/en-US/docs/Web/JavaScript/Reference/Statements/for-await...of) even in older browsers and JavaScript runtimes that have no [top-level await](/en-US/docs/Web/JavaScript/Reference/Operators/await#top_level_await): | ||
|
||
```js | ||
const getFileStream = async (url) => { | ||
// implementation | ||
}; | ||
|
||
(async () => { | ||
const stream = await getFileStream("https://domain.name/path/file.ext"); | ||
for await (const chunk of stream) { | ||
console.log({ chunk }); | ||
} | ||
})(); | ||
``` | ||
|
||
### The module pattern | ||
|
||
We would also use IIFE to create private and public variables and methods. For a more sophisticated use of the module | ||
pattern and other use of IIFE, you could see the book Learning JavaScript Design Patterns by Addy Osmani. | ||
|
||
```js | ||
const makeWithdraw = (balance) => | ||
((copyBalance) => { | ||
let balance = copyBalance; // This variable is private | ||
const doBadThings = () => { | ||
console.log("I will do bad things with your money"); | ||
}; | ||
doBadThings(); | ||
return { | ||
withdraw(amount) { | ||
if (balance >= amount) { | ||
balance -= amount; | ||
return balance; | ||
} | ||
return "Insufficient money"; | ||
}, | ||
}; | ||
})(balance); | ||
|
||
const firstAccount = makeWithdraw(100); // "I will do bad things with your money" | ||
console.log(firstAccount.balance); // undefined | ||
console.log(firstAccount.withdraw(20)); // 80 | ||
console.log(firstAccount.withdraw(30)); // 50 | ||
console.log(firstAccount.doBadThings); // undefined; this method is private | ||
const secondAccount = makeWithdraw(20); // "I will do bad things with your money" | ||
console.log(secondAccount.withdraw(30)); // "Insufficient money" | ||
console.log(secondAccount.withdraw(20)); // 0 | ||
``` | ||
|
||
### For loop with var before ES6 | ||
|
||
We could see the following use of IIFE in some old code, before the introduction of the statements **let** and **const** | ||
in **ES6** and the block scope. With the statement **var**, we have only function scopes and the global scope. | ||
Suppose we want to create 2 buttons with the texts Button 0 and Button 1 and when we click | ||
them, we would like them to alert 0 and 1. The following code doesn't work: | ||
|
||
```js | ||
for (var i = 0; i < 2; i++) { | ||
const button = document.createElement("button"); | ||
button.innerText = `Button ${i}`; | ||
button.onclick = function () { | ||
console.log(i); | ||
}; | ||
document.body.appendChild(button); | ||
} | ||
console.log(i); // 2 | ||
``` | ||
|
||
When clicked, both Button 0 and Button 1 alert 2 because `i` is global, | ||
with the last value 2. To fix this problem before ES6, we could use the IIFE pattern: | ||
|
||
```js | ||
for (var i = 0; i < 2; i++) { | ||
const button = document.createElement("button"); | ||
button.innerText = `Button ${i}`; | ||
button.onclick = (function (copyOfI) { | ||
return function () { | ||
console.log(copyOfI); | ||
}; | ||
})(i); | ||
document.body.appendChild(button); | ||
} | ||
console.log(i); // 2 | ||
``` | ||
|
||
When clicked, Buttons 0 and 1 alert 0 and 1. | ||
The variable `i` is globally defined. | ||
Using the statement **let**, we could simply do: | ||
|
||
```js | ||
for (let i = 0; i < 2; i++) { | ||
const button = document.createElement("button"); | ||
button.innerText = `Button ${i}`; | ||
button.onclick = function () { | ||
console.log(i); | ||
}; | ||
document.body.appendChild(button); | ||
} | ||
console.log(i); // Uncaught ReferenceError: i is not defined. | ||
``` | ||
|
||
When clicked, these buttons alert 0 and 1. | ||
For code examples, see the [`function` expression](/en-US/docs/Web/JavaScript/Reference/Operators/function) and [`async function` expression](/en-US/docs/Web/JavaScript/Reference/Operators/async_function) reference pages. | ||
|
||
## See also | ||
|
||
- [IIFE](https://en.wikipedia.org/wiki/Immediately-invoked_function_expression) (Wikipedia) | ||
- [Comma operator](/en-US/docs/Web/JavaScript/Reference/Operators/Comma_operator) | ||
- Related glossary terms: | ||
- {{Glossary("Function")}} | ||
- {{Glossary("Self-Executing Anonymous Function")}} |
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At first read, this sounds to me as a reader like
rather than an explicit pattern.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks accurate.