Skip to content

Commit d2bf986

Browse files
committed
docs: design patterns
1 parent 9b983b8 commit d2bf986

3 files changed

+255
-69
lines changed

module-1.1-closures-and-scopes.md

Lines changed: 46 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,70 @@
1-
# Module 1: Advanced JavaScript Concepts
1+
## Module 1: Advanced JavaScript Concepts
2+
### 1.1. Closures and Scopes
23

3-
## 1.1. Closures and Scopes**
4+
In JavaScript, closures and scopes are fundamental concepts that play a crucial role in managing variables and controlling access to data. Understanding how they work is essential for advanced JavaScript development. Let's delve into these concepts with explanations and examples:
45

5-
**Description:**
6+
#### Scopes:
7+
Scopes in JavaScript refer to the visibility and accessibility of variables. JavaScript has two primary types of scopes:
68

7-
Closures and scopes are fundamental concepts in JavaScript that play a crucial role in understanding how variables and functions are organized and accessed within your code. This section delves into the details of these concepts.
9+
**1. Global Scope:** Variables declared outside of any function are in the global scope. These variables are accessible from anywhere in your code.
810

9-
**Topics Covered:**
10-
11-
- **Scopes:** JavaScript has two main types of scope: global scope and local (or function) scope. In this part, you'll learn how scope works and how variables are accessed within these scopes.
12-
13-
- **Lexical Scoping:** JavaScript uses lexical scoping, which means that the scope of a variable is determined by its location within the source code. You'll explore how lexical scoping works and how it impacts your code.
14-
15-
- **Closures:** Closures are an advanced concept that occurs when a function is defined within another function and "remembers" its outer function's variables even after the outer function has finished executing. You'll learn how closures work and how to use them effectively.
11+
**Example:**
12+
```javascript
13+
const globalVar = 10;
1614

17-
- **Scope Chain:** Understanding the scope chain is essential for working with closures. You'll explore how JavaScript creates a chain of nested scopes and how this impacts variable resolution.
15+
function myFunction() {
16+
console.log(globalVar); // Accessible within the function
17+
}
1818

19-
- **Garbage Collection:** Closures can sometimes lead to memory leaks if not managed properly. This section covers the importance of garbage collection and how to ensure that resources are released appropriately when they are no longer needed.
19+
myFunction();
20+
console.log(globalVar); // Accessible outside the function
21+
```
2022

21-
**Practical Application:**
23+
**2. Local (Function) Scope:** Variables declared within a function are in the local scope. They are accessible only within that function.
2224

23-
Closures and scopes are fundamental for managing variables and functions in JavaScript. They are extensively used in real-world scenarios like managing private variables, creating modular code, implementing data encapsulation, and building custom functions and libraries.
25+
**Example:**
26+
```javascript
27+
function myFunction() {
28+
const localVar = 5; // Local variable
29+
console.log(localVar); // Accessible within the function
30+
}
2431

25-
**Examples:**
32+
myFunction();
33+
console.log(localVar); // Results in an error; localVar is not defined here
34+
```
2635

27-
Here's a simple example of closures and scopes:
36+
#### Closures:
37+
A closure is a function that "closes over" variables from its outer scope, allowing it to access and manipulate those variables even after the outer function has finished executing. Closures are powerful because they enable data encapsulation and can be used to create private variables.
2838

39+
**Example:**
2940
```javascript
3041
function outerFunction() {
31-
var outerVar = 'I am from the outer function';
42+
const outerVar = 'I am from the outer function';
3243

3344
function innerFunction() {
34-
var innerVar = 'I am from the inner function';
35-
console.log(outerVar); // Accesses the outer variable
45+
console.log(outerVar); // Accesses outerVar from the outer function
3646
}
3747

3848
return innerFunction;
3949
}
4050

41-
var closure = outerFunction();
42-
closure(); // Logs "I am from the outer function"
51+
const myClosure = outerFunction();
52+
myClosure(); // Logs "I am from the outer function"
4353
```
4454

45-
In this example, `innerFunction` is a closure that can access the `outerVar` variable even after `outerFunction` has completed execution.
55+
In the example above, `innerFunction` is a closure because it "closes over" `outerVar` from the outer function. Even though `outerFunction` has completed its execution, `myClosure` retains access to `outerVar`.
56+
57+
Closures are commonly used in scenarios like maintaining state in functional programming and creating private data in object-oriented programming.
58+
59+
#### Practical Uses:
60+
Closures are handy in various JavaScript patterns and idioms. Some practical uses include:
61+
62+
1. **Data Encapsulation:** Closures can be used to create private variables and encapsulate data, allowing you to control access and modification.
63+
64+
2. **Function Factories:** You can use closures to create functions with specific behavior or configurations.
65+
66+
3. **Callbacks:** Closures are often used in callback functions and event handling to maintain context and access external data.
4667

47-
**Key Takeaways:**
68+
4. **Memoization:** Closures can be employed to cache function results and optimize performance.
4869

49-
Understanding closures and scopes is critical for writing efficient and maintainable JavaScript code. Mastery of these concepts will enable you to create modular, encapsulated, and reusable code, leading to more robust and efficient applications.
70+
Understanding closures and scopes is crucial for building maintainable, efficient, and secure JavaScript applications. They are core concepts for advanced JavaScript developers.
Lines changed: 55 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,75 @@
1-
# Module 1: Advanced JavaScript Concepts
1+
## Module 1: Advanced JavaScript Concepts
2+
### 1.2. Promises and Async/Await
23

3-
## 1.2. Promises and Async/Await**
4+
Promises and the async/await syntax are critical concepts in modern JavaScript for managing asynchronous operations. They simplify asynchronous code and make it more readable and maintainable. Let's explore these concepts in depth with examples:
45

5-
**Description:**
6+
#### Promises:
7+
Promises are objects that represent the eventual completion or failure of an asynchronous operation. They provide a way to work with asynchronous code in a more structured and organized manner.
68

7-
Promises and Async/Await are crucial concepts in modern JavaScript, specifically designed to handle asynchronous operations more efficiently and readably. This section explores these concepts and their applications in detail.
9+
A promise can be in one of three states:
810

9-
**Topics Covered:**
11+
1. **Pending:** The initial state, representing that the operation has not yet completed.
12+
2. **Fulfilled:** The state when the operation has succeeded, and a result is available.
13+
3. **Rejected:** The state when the operation has failed, and an error reason is available.
1014

11-
- **Promises:** Promises are a way to manage asynchronous operations and provide a cleaner alternative to callback functions. You'll learn how to create, use, and chain promises to handle asynchronous tasks effectively.
15+
**Example: Using Promises**
1216

13-
- **Promise States:** Promises have three states: pending, fulfilled, and rejected. Understanding these states is essential for managing asynchronous operations gracefully.
14-
15-
- **Error Handling:** Promises allow for streamlined error handling using `.catch()` and handling errors within the promise chain.
16-
17-
- **Async/Await:** Async/Await is a more recent addition to JavaScript, simplifying asynchronous code even further. You'll explore how to write asynchronous code that looks like synchronous code and effectively use `async` functions and the `await` keyword.
18-
19-
- **Parallel and Sequential Execution:** You'll learn how to orchestrate multiple asynchronous operations, executing them in parallel or sequentially, depending on your requirements.
17+
```javascript
18+
function asyncOperation() {
19+
return new Promise((resolve, reject) => {
20+
setTimeout(() => {
21+
const result = Math.random();
22+
if (result >= 0.5) {
23+
resolve(result); // Resolve with a result
24+
} else {
25+
reject("Operation failed"); // Reject with an error
26+
}
27+
}, 1000);
28+
});
29+
}
2030

21-
**Practical Application:**
31+
asyncOperation()
32+
.then(result => {
33+
console.log("Operation succeeded with result:", result);
34+
})
35+
.catch(error => {
36+
console.error("Operation failed with error:", error);
37+
});
38+
```
2239

23-
Promises and Async/Await are extensively used in modern web development for handling tasks like making API requests, reading/writing files, and managing concurrent operations. They improve code readability and maintainability, making asynchronous code easier to work with.
40+
In the example above, we create a promise that simulates an asynchronous operation and resolves or rejects based on a random number. We then use `.then()` to handle success and `.catch()` to handle errors.
2441

25-
**Examples:**
42+
#### Async/Await:
43+
The async/await syntax provides a more readable and synchronous-like way to work with promises. The `async` keyword is used to declare an asynchronous function, and the `await` keyword is used inside such functions to pause the execution until a promise is resolved.
2644

27-
Here's an example of using Promises and Async/Await to fetch data from an API:
45+
**Example: Using Async/Await**
2846

2947
```javascript
30-
// Using Promises
31-
fetch('https://api.example.com/data')
32-
.then((response) => {
33-
if (!response.ok) {
34-
throw new Error('Network response was not ok');
35-
}
36-
return response.json();
37-
})
38-
.then((data) => {
39-
console.log(data);
40-
})
41-
.catch((error) => {
42-
console.error('There was a problem:', error);
43-
});
44-
45-
// Using Async/Await
46-
async function fetchData() {
48+
async function performAsyncTask() {
4749
try {
48-
const response = await fetch('https://api.example.com/data');
49-
if (!response.ok) {
50-
throw new Error('Network response was not ok');
51-
}
52-
const data = await response.json();
53-
console.log(data);
50+
const result = await asyncOperation();
51+
console.log("Operation succeeded with result:", result);
5452
} catch (error) {
55-
console.error('There was a problem:', error);
53+
console.error("Operation failed with error:", error);
5654
}
5755
}
5856

59-
fetchData();
57+
performAsyncTask();
6058
```
6159

62-
**Key Takeaways:**
60+
In this example, we declare an `async` function `performAsyncTask`, which uses `await` to pause until the `asyncOperation` promise is resolved or rejected. This makes the code look more synchronous and easier to read.
61+
62+
#### Practical Uses:
63+
Promises and async/await are widely used in JavaScript for various asynchronous tasks, including:
64+
65+
1. **HTTP Requests:** Promises are often used to manage AJAX requests, making it easier to handle responses.
66+
67+
2. **Timeouts and Intervals:** Promises are useful for scheduling tasks to run after a specified time interval.
68+
69+
3. **File I/O:** Promises simplify reading and writing files in Node.js applications.
70+
71+
4. **Database Queries:** Promises make it easier to work with databases and manage queries.
72+
73+
5. **Parallel and Sequential Execution:** Async/await allows you to control the flow of asynchronous operations, whether they need to run in parallel or sequentially.
6374

64-
Promises and Async/Await are essential tools for managing asynchronous operations in JavaScript. They simplify error handling, improve code readability, and are widely used for tasks involving network requests, file I/O, and more. Understanding these concepts is crucial for modern web development.
75+
Promises and async/await have become integral tools for handling asynchronous operations in JavaScript, improving code readability and maintainability while reducing callback hell.

module-1.4-design-patterns.md

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
## Module 1: Advanced JavaScript Concepts
2+
### 1.4. Design Patterns
3+
4+
Design patterns are reusable solutions to common problems that arise during software design and development. In JavaScript, as in any other programming language, design patterns help developers create maintainable and efficient code by following established best practices. Let's explore some design patterns in-depth with examples:
5+
6+
### 1. Singleton Pattern:
7+
8+
The Singleton pattern ensures that a class has only one instance and provides a global point of access to that instance. It's useful when exactly one object is needed to coordinate actions across a system.
9+
10+
**Example: Singleton Pattern**
11+
12+
```javascript
13+
const Singleton = (function () {
14+
let instance;
15+
16+
function createInstance() {
17+
return {
18+
data: "This is the singleton instance."
19+
};
20+
}
21+
22+
return {
23+
getInstance: function () {
24+
if (!instance) {
25+
instance = createInstance();
26+
}
27+
return instance;
28+
}
29+
};
30+
})();
31+
32+
const instance1 = Singleton.getInstance();
33+
const instance2 = Singleton.getInstance();
34+
35+
console.log(instance1 === instance2); // true
36+
console.log(instance1.data); // "This is the singleton instance."
37+
```
38+
39+
In this example, the Singleton pattern ensures that there's only one instance of the `Singleton` object.
40+
41+
### 2. Factory Pattern:
42+
43+
The Factory pattern is used for creating objects without specifying the exact class of the object that will be created. It defines an interface for creating objects, but the specific object is determined at runtime.
44+
45+
**Example: Factory Pattern**
46+
47+
```javascript
48+
class Circle {
49+
constructor(radius) {
50+
this.radius = radius;
51+
}
52+
}
53+
54+
class Square {
55+
constructor(sideLength) {
56+
this.sideLength = sideLength;
57+
}
58+
}
59+
60+
function createShape(type, size) {
61+
if (type === "circle") {
62+
return new Circle(size);
63+
} else if (type === "square") {
64+
return new Square(size);
65+
}
66+
}
67+
68+
const circle = createShape("circle", 5);
69+
const square = createShape("square", 4);
70+
71+
console.log(circle instanceof Circle); // true
72+
console.log(square instanceof Square); // true
73+
```
74+
75+
The Factory pattern allows us to create objects (shapes in this case) without needing to know the specific class details.
76+
77+
### 3. Observer Pattern:
78+
79+
The Observer pattern is used when an object (the subject) maintains a list of its dependents (observers) and notifies them of state changes, typically by calling one of their methods.
80+
81+
**Example: Observer Pattern**
82+
83+
```javascript
84+
class Subject {
85+
constructor() {
86+
this.observers = [];
87+
}
88+
89+
addObserver(observer) {
90+
this.observers.push(observer);
91+
}
92+
93+
removeObserver(observer) {
94+
this.observers = this.observers.filter(obs => obs !== observer);
95+
}
96+
97+
notify(message) {
98+
this.observers.forEach(observer => observer.update(message));
99+
}
100+
}
101+
102+
class Observer {
103+
update(message) {
104+
console.log("Received message:", message);
105+
}
106+
}
107+
108+
const subject = new Subject();
109+
const observer1 = new Observer();
110+
const observer2 = new Observer();
111+
112+
subject.addObserver(observer1);
113+
subject.addObserver(observer2);
114+
115+
subject.notify("Hello, observers!");
116+
```
117+
118+
In this example, the `Observer` pattern allows multiple observers to be notified when the subject's state changes.
119+
120+
### 4. Module Pattern:
121+
122+
The Module pattern allows you to create private and public encapsulation for your code, making it more organized and less prone to conflicts.
123+
124+
**Example: Module Pattern**
125+
126+
```javascript
127+
const Module = (function () {
128+
// Private variable
129+
let privateVar = 10;
130+
131+
// Private function
132+
function privateFunction() {
133+
return privateVar;
134+
}
135+
136+
// Public interface
137+
return {
138+
publicFunction: function () {
139+
return privateFunction();
140+
},
141+
changeVar: function (newValue) {
142+
privateVar = newValue;
143+
}
144+
};
145+
})();
146+
147+
console.log(Module.publicFunction()); // 10
148+
Module.changeVar(20);
149+
console.log(Module.publicFunction()); // 20
150+
```
151+
152+
The Module pattern allows for the creation of public and private members, promoting encapsulation.
153+
154+
These are just a few examples of design patterns in JavaScript. Design patterns provide a structured approach to solving common software design problems, making your code more organized, efficient, and maintainable. Depending on the situation, different patterns can be applied to solve specific issues in your code.

0 commit comments

Comments
 (0)