Skip to content

Commit 9cba15f

Browse files
authored
Merge pull request Aman0509#4 from Aman0509/advanced-function-concepts
Advanced function concepts
2 parents 202603e + b0154ae commit 9cba15f

File tree

4 files changed

+269
-0
lines changed

4 files changed

+269
-0
lines changed
Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
# Advanced Function Concepts
2+
3+
| Contents |
4+
| :--- |
5+
| [Pure Functions and Side-Effect](#pure-functions-and-its-side-effect) |
6+
| [Factory Functions](#factory-functions) |
7+
| [Closures](#closures) |
8+
9+
 
10+
11+
:abacus: [Understand with Code](summary-with-code/app.js)
12+
13+
## [Pure Functions and Side-Effects](https://drive.google.com/uc?export=view&id=1J1QRcr3UMC-h4zeQhgv6INAfitnKWa2_)
14+
15+
In JavaScript, a pure function is a function that:
16+
17+
- Given the same inputs, always returns the same output.
18+
- Has no side effects, meaning it doesn't modify anything outside of its own scope, including global variables, DOM elements, or any other external state.
19+
20+
Here's an example of a pure function:
21+
22+
```javascript
23+
function sum(a, b) {
24+
return a + b;
25+
}
26+
```
27+
28+
The `sum` function takes two arguments and always returns their sum. It doesn't have any side effects because it doesn't modify anything outside of its scope.
29+
30+
On the other hand, an impure function is a function that:
31+
32+
- Doesn't always return the same output for the same inputs.
33+
- Has side effects, meaning it modifies something outside of its own scope.
34+
35+
Here's an example of an impure function:
36+
37+
```javascript
38+
let counter = 0;
39+
40+
function increment() {
41+
counter++;
42+
return counter;
43+
}
44+
```
45+
46+
The `increment` function modifies the global counter variable every time it is called, which is a side effect. Additionally, it doesn't always return the same output for the same input, since it returns a different value each time it is called.
47+
48+
Side effects can be problematic in code because they can make it harder to reason about what a function does and can introduce bugs. It's generally a good practice to write as many pure functions as possible and minimize the number of impure functions.
49+
50+
Readings:
51+
52+
- [Pure and Impure Functions in JavaScript: A Complete Guide](https://www.syncfusion.com/blogs/post/pure-and-impure-functions-in-javascript-a-complete-guide.aspx)
53+
54+
- [Pure vs Impure Functions in Functional Programming – What's the Difference?](https://www.freecodecamp.org/news/pure-function-vs-impure-function/)
55+
56+
## Factory Functions
57+
58+
A factory function is a function that returns another function or object. It's called a factory function because it creates and returns new objects without having to use the `new` keyword or a class constructor.
59+
60+
Here's an example of a factory function that creates objects representing cars:
61+
62+
```javascript
63+
function createCar(make, model, year) {
64+
return {
65+
make,
66+
model,
67+
year,
68+
getInfo: function() {
69+
return `${this.year} ${this.make} ${this.model}`;
70+
}
71+
};
72+
}
73+
74+
const myCar = createCar('Honda', 'Civic', 2022);
75+
console.log(myCar.getInfo()); // "2022 Honda Civic"
76+
```
77+
78+
In this example, `createCar` is a factory function that takes three arguments: `make`, `model`, and `year`. It returns an object that has properties for `make`, `model`, and `year`, as well as a method `getInfo` that returns a string representation of the car's make, model, and year.
79+
80+
To create a new car object, we simply call the `createCar` function with the appropriate arguments, and assign the returned object to a variable (`myCar` in this case). We can then call the `getInfo` method on the `myCar` object to get a string representation of the car's make, model, and year.
81+
82+
Here's an example of a factory function that returns a function:
83+
84+
```javascript
85+
function createMultiplier(multiplier) {
86+
return function(number) {
87+
return number * multiplier;
88+
}
89+
}
90+
91+
const double = createMultiplier(2);
92+
const triple = createMultiplier(3);
93+
94+
console.log(double(5)); // output: 10
95+
console.log(triple(5)); // output: 15
96+
```
97+
98+
Factory functions can be useful in situations where you need to create many similar objects, or where you want to encapsulate the creation of an object so that it can be customized or reused in different contexts.
99+
100+
Readings:
101+
102+
- [What are factory functions in JavaScript ?](https://www.geeksforgeeks.org/what-are-factory-functions-in-javascript/)
103+
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.
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/* Pure Function */
2+
3+
function add(num1, num2) {
4+
return num1 + num2;
5+
}
6+
7+
console.log(add(4, 5));
8+
console.log(add(19, 3));
9+
10+
/* Impure Function */
11+
12+
// On every reload, the returned value of these function will change
13+
function addRandom(num) {
14+
return num + Math.random();
15+
}
16+
17+
console.log(addRandom(7));
18+
console.log(addRandom(17));
19+
20+
// A function is also considered as impure if it introduces side effect, which means changes anything outside of function
21+
let previousResult = 0;
22+
function addMoreNumbers(num1, num2){
23+
const sum = num1 + num2;
24+
previousResult = sum; // Side-Effect
25+
return sum;
26+
}
27+
28+
console.log(addMoreNumbers(34, 21), previousResult);
29+
30+
const hobbies = ['Sports', 'Cooking'];
31+
32+
function printHobbies(hobbies) {
33+
console.log(hobbies);
34+
hobbies.push('Gardening');
35+
}
36+
37+
printHobbies(hobbies);
38+
console.log(hobbies);
39+
40+
/* Factory Functions */
41+
42+
function createTaxCalculator(income) {
43+
function calculateTax(taxPercent) {
44+
return (income*taxPercent)/100;
45+
}
46+
return calculateTax;
47+
}
48+
49+
income = createTaxCalculator(745334);
50+
51+
console.log(income(5));
52+
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!
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<meta http-equiv="X-UA-Compatible" content="ie=edge">
7+
<title>Advanced Functions</title>
8+
<script src="app.js" defer></script>
9+
</head>
10+
<body>
11+
12+
</body>
13+
</html>

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
- [Constructor Functions and Prototypes](Constructor-Functions-and-Prototypes/README.md)
1414
- [Advanced DOM APIs](Advanced-DOM-APIs/README.md)
1515
- [Working with Events](Working-with-Events/README.md)
16+
- [Advanced Function Concepts](Advanced-Function-Concepts/README.md)
1617

1718
## References
1819

0 commit comments

Comments
 (0)