-
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
Conversation
dda2933
to
709613a
Compare
Preview URLs
Flaws (18)Note! 1 document with no flaws that don't need to be listed. 🎉 URL:
URL:
URL:
External URLs (1)URL:
(comment last updated: 2025-01-03 22:23:28) |
d2ffb51
to
3e917eb
Compare
3e917eb
to
8b04261
Compare
``` | ||
|
||
It is a design pattern which is also known as a {{glossary("Self-Executing Anonymous Function")}} and 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 comment
The 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 comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed since it doesn't have to be anonymous
or even enclosed within ()
. And the scope the function expression creates does not belong to the enclosing ()
:
const [uncleDavidStr, uncleDavidFunc] = function uncleDavidFunc() {
return ['Uncle David', uncleDavidFunc];
}();
(uncleDavidFunc, function uncleDavidFunc() {
})(); // ReferenceError: uncleDavidFunc is not defined
@@ -6,45 +6,74 @@ 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. |
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
function implicitlyRunsImmediatelyForSomeReason() {}
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.
files/en-us/glossary/iife/index.md
Outdated
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 | ||
important to limit the number of variables at the top level of a script | ||
(this advice [does not apply to module code](/en-US/docs/Web/JavaScript/Guide/Modules#other_differences_between_modules_and_classic_scripts)). |
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.
I don't think leaving out modules is a good idea, since it implies that it's okay to pollute the module scope (and pollute
implies that the scope will keep variables that are no longer needed).
const year2000 = new Date('2000');
const currentDate = new Date();
export const isAfterYear2000 = currentDate > year2000;
export const isAfterYear2000 = (() => {
const year2000 = new Date('2000');
const currentDate = new Date();
return currentDate > year2000;
})();
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.
There's a critical conceptual difference between "I want to avoid an intermediate variable for all the reasons you might ordinarily want to avoid an intermediate variable" and "if I create an intermediate variable here it will be a global variable" (which applies to top level of scripts only). My goal is to convey that difference.
Do you have a suggestion how I might communicate that better? I.e. to communicate that if it's not the top level of a script, this is still a useful pattern, but it doesn't solve nearly as catastrophic a problem as the script global variable problem.
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.
It doesn't look necessary to mention modules when the focus is already on the global namespace. Though it's true the advice is more lenient with modules.
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 good without the exclusion of modules.
files/en-us/glossary/iife/index.md
Outdated
// IIFE being used to initialize a variable | ||
const value = (() => { | ||
const randomValue = Math.random(); | ||
if (randomValue > 0.5) { |
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.
if (randomValue > 0.5) { | |
if (randomValue >= 0.5) { |
Nitpicking but for an even distribution
, the true branch should include the 0.5 value.
Range for the false branch: 0 <= x < 0.5
Range for the true branch: 0.5 <= x < 1
@@ -6,45 +6,74 @@ 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. |
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.
``` | ||
|
||
It is a design pattern which is also known as a {{glossary("Self-Executing Anonymous Function")}} and 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 comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed since it doesn't have to be anonymous
or even enclosed within ()
. And the scope the function expression creates does not belong to the enclosing ()
:
const [uncleDavidStr, uncleDavidFunc] = function uncleDavidFunc() {
return ['Uncle David', uncleDavidFunc];
}();
(uncleDavidFunc, function uncleDavidFunc() {
})(); // ReferenceError: uncleDavidFunc is not defined
This page is getting too long. In general glossary entries should try to be a few paragraphs. I will try to move this to the JS reference instead. |
Moved the examples around. @kirkwaiblinger @60x20 WDYT? |
}; | ||
})(balance); | ||
|
||
const firstAccount = makeWithdraw(100); // "I will do bad things with your money" |
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.
neither here nor there really, but I really dislike this example
- The specific code example is hard to follow and just.... weird 😆
- I'm not sure this use pattern in general is that useful especially with
#private
class members these days. But I could be wrong about this
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.
It is a bit weird, but this is exactly how modules work, so I think it's still useful, at least not any less than the for
loop scoping example below. We already said that "Many traditional use cases of IIFEs have been obsoleted by new syntax features such as modules and block-scoped declarations", so I'd like to keep this for now.
@Josh-Cena I'm happy! |
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.
👍 Thanks a lot!
Description
Added examples of IIFE use cases, and made changes to confusing and misleading information.
Motivation
I was pointing a github user to the docs for IIFEs, since they were in a position where they were absolutely required to use multiple statements in a position that only accepted one, which is perfect use case for an IIFE, see marilari88/zod-playground#130 (comment) (and also marilari88/zod-playground#81). But when I looked at the docs page I had linked... I found it to be extremely difficult to understand, and didn't really address the use case I was referring to at all.
Additional details
Related issues and pull requests