Skip to content

Commit b0154ae

Browse files
committed
learn about Closures
1 parent 665e7ce commit b0154ae

File tree

2 files changed

+105
-1
lines changed

2 files changed

+105
-1
lines changed

Advanced-Function-Concepts/README.md

Lines changed: 93 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44
| :--- |
55
| [Pure Functions and Side-Effect](#pure-functions-and-its-side-effect) |
66
| [Factory Functions](#factory-functions) |
7+
| [Closures](#closures) |
8+
9+
 
10+
11+
:abacus: [Understand with Code](summary-with-code/app.js)
712

813
## [Pure Functions and Side-Effects](https://drive.google.com/uc?export=view&id=1J1QRcr3UMC-h4zeQhgv6INAfitnKWa2_)
914

@@ -96,4 +101,91 @@ Readings:
96101

97102
- [What are factory functions in JavaScript ?](https://www.geeksforgeeks.org/what-are-factory-functions-in-javascript/)
98103

99-
- [JavaScript Factory Functions](https://www.javascripttutorial.net/javascript-factory-functions/)
104+
- [JavaScript Factory Functions](https://www.javascripttutorial.net/javascript-factory-functions/)
105+
106+
## [Closures](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures)
107+
108+
In JavaScript, a closure is created when a function is defined inside another function and the inner function accesses variables from the outer function's scope. The inner function has access to the outer function's variables, parameters, and even other inner functions, even after the outer function has returned. This behavior is possible because of how JavaScript handles scope and variable declaration.
109+
110+
Here's an example to illustrate closures in JavaScript:
111+
112+
```javascript
113+
function createCounter() {
114+
let count = 0;
115+
116+
function increment() {
117+
count++;
118+
console.log(count);
119+
}
120+
121+
return increment;
122+
}
123+
124+
const counter = createCounter();
125+
126+
counter(); // logs 1
127+
counter(); // logs 2
128+
counter(); // logs 3
129+
```
130+
131+
In this example, `createCounter()` is a function that returns another function called `increment()`. Inside `createCounter()`, we define a variable called `count` and initialize it to 0. We also define `increment()`, which increments `count` by 1 and logs its value to the console.
132+
133+
We then return `increment()`, which means that calling `createCounter()` actually returns the `increment()` function. We assign this function to a variable called `counter`, which allows us to call `increment()` as many times as we want.
134+
135+
When we call `counter()` for the first time, it logs `1` to the console. This is because `counter()` is actually calling the `increment()` function that was defined inside `createCounter()`. This inner function has access to the `count` variable that was defined in the outer function's scope, so it can increment and log its value.
136+
137+
When we call `counter()` again, it logs `2` to the console, because the `count` variable is still accessible to the `increment()` function. We can call `counter()` as many times as we want, and the value of `count` will continue to increment and be logged to the console.
138+
139+
This is an example of a closure in JavaScript, because the `increment()` function has access to the `count` variable even after `createCounter()` has returned. The inner function "closes over" the outer function's scope and remembers its variables, allowing us to create a counter that persists between function calls.
140+
141+
> All functions in JavaScript are closures. This is because every function in JavaScript has access to the variables and parameters of its outer or parent scope, even after the outer function has returned.
142+
143+
### Closures and Memory Management
144+
145+
If every function logs all surrounding variables, it could potentially lead to a negative impact on memory, especially in large applications with many variables. A function may log in many variables that it doesn't actually use, but since the function closes over them, JavaScript won't get rid of them.
146+
147+
This could result in a memory issue, but modern JavaScript engines are designed to optimize this behavior by tracking variable usage. If a variable isn't used by any functions or elsewhere in the code, the engine will safely dispose of it. This way, you don't need to manually reset all unused variables as the engine will handle it for you. The JavaScript engines are intelligent and efficient enough to optimize this process without affecting your program's stability.
148+
149+
Readings:
150+
151+
- [Learn JavaScript Closures with Code Examples](https://www.freecodecamp.org/news/lets-learn-javascript-closures-66feb44f6a44/)
152+
153+
- [JavaScript Closures](https://www.javascripttutorial.net/javascript-closure/)
154+
155+
### Immediately Invoked Function Expression (IIFE)
156+
157+
In JavaScript, especially in older scripts, you sometimes find a pattern described as **IIFEs**. **IIFE** stands for "Immediately Invoked Function Expression" and the pattern you might find looks like this (directly in a script file):
158+
159+
```javascript
160+
(function() {
161+
var age = 30;
162+
console.log(age); // 30
163+
})()
164+
165+
console.log(age); // Error: "age is not defined"
166+
```
167+
168+
What's that?
169+
170+
We see a function expression which calls itself (please note the `()` right after the function).
171+
172+
It's NOT a function declaration because it's wrapped in `()`. That happens on purpose since you can't immediately execute function declarations.
173+
174+
**But why would you write some code?**
175+
176+
Please note that the snippet uses `var`, not `let` or `const`. Remember that `var` does not use block scope but only differ between global and function scope.
177+
178+
As a consequence, it was hard to control where variables were available. Variables outside of function always were available globally. Well, IIFEs solve that problem since the script (or parts of it) essentially are wrapped in a function and function scope is used.
179+
180+
**Nowadays, this is not really required anymore.** With `let` and `const` we got block scope and if you want to restrict where variables are available (outside of functions, `if` statements, `for` loops etc, where you automatically have scoped variables since these structures create blocks), you can simply wrap the code that should have scoped variables with `{}`.
181+
182+
```javascript
183+
{
184+
const age = 30;
185+
console.log(age); // 30
186+
}
187+
188+
console.log(age); // Error: "age is not defined"
189+
```
190+
191+
Not something you see too often but something that is possible.

Advanced-Function-Concepts/summary-with-code/app.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,15 @@ income = createTaxCalculator(745334);
5050

5151
console.log(income(5));
5252
console.log(income(10));
53+
54+
/* Closures */
55+
56+
let userName = 'John';
57+
58+
function greetUser() {
59+
console.log('Hello Mr. ' + userName + '!');
60+
}
61+
62+
userName = 'Wick';
63+
64+
greetUser(); // Hello Mr. Wick!

0 commit comments

Comments
 (0)