From 0e60314cf00c27b146e3a51a3b1c32eef075911a Mon Sep 17 00:00:00 2001 From: Ajay Dhangar Date: Tue, 8 Sep 2026 21:37:08 +0530 Subject: [PATCH] complited basic docs --- blog/2019-05-28-first-blog-post.md | 12 - blog/2019-05-29-long-blog-post.md | 44 --- blog/2021-08-01-mdx-blog-post.mdx | 24 -- blog/_scripts/closures-state-retention.js | 19 ++ blog/_scripts/variable-scoping-and-tdz.js | 40 +++ ...emystifying-closures-and-lexical-scope.mdx | 151 +++++++++ blog/var-let-const-scope-hoisting.mdx | 184 +++++++++++ docs/01-getting-started/introduction.md | 11 +- .../clean-code-and-performance.md | 173 +++++++++++ .../design-patterns.md | 287 ++++++++++++++++++ .../debounce-throttle-optimization.js | 23 ++ docs/_scripts/fibonacci-gen.js | 2 +- docs/_scripts/observer-pattern.js | 21 ++ static/img/blogs/closures-lexical-scope.png | Bin 0 -> 11463 bytes static/img/blogs/var-let-const.svg | 50 +++ 15 files changed, 950 insertions(+), 91 deletions(-) delete mode 100644 blog/2019-05-28-first-blog-post.md delete mode 100644 blog/2019-05-29-long-blog-post.md delete mode 100644 blog/2021-08-01-mdx-blog-post.mdx create mode 100644 blog/_scripts/closures-state-retention.js create mode 100644 blog/_scripts/variable-scoping-and-tdz.js create mode 100644 blog/demystifying-closures-and-lexical-scope.mdx create mode 100644 blog/var-let-const-scope-hoisting.mdx create mode 100644 docs/_scripts/debounce-throttle-optimization.js create mode 100644 docs/_scripts/observer-pattern.js create mode 100644 static/img/blogs/closures-lexical-scope.png create mode 100644 static/img/blogs/var-let-const.svg diff --git a/blog/2019-05-28-first-blog-post.md b/blog/2019-05-28-first-blog-post.md deleted file mode 100644 index d3032ef..0000000 --- a/blog/2019-05-28-first-blog-post.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -slug: first-blog-post -title: First Blog Post -authors: [slorber, yangshun] -tags: [hola, docusaurus] ---- - -Lorem ipsum dolor sit amet... - - - -...consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet diff --git a/blog/2019-05-29-long-blog-post.md b/blog/2019-05-29-long-blog-post.md deleted file mode 100644 index eb4435d..0000000 --- a/blog/2019-05-29-long-blog-post.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -slug: long-blog-post -title: Long Blog Post -authors: yangshun -tags: [hello, docusaurus] ---- - -This is the summary of a very long blog post, - -Use a `` comment to limit blog post size in the list view. - - - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet diff --git a/blog/2021-08-01-mdx-blog-post.mdx b/blog/2021-08-01-mdx-blog-post.mdx deleted file mode 100644 index 0c4b4a4..0000000 --- a/blog/2021-08-01-mdx-blog-post.mdx +++ /dev/null @@ -1,24 +0,0 @@ ---- -slug: mdx-blog-post -title: MDX Blog Post -authors: [slorber] -tags: [docusaurus] ---- - -Blog posts support [Docusaurus Markdown features](https://docusaurus.io/docs/markdown-features), such as [MDX](https://mdxjs.com/). - -:::tip - -Use the power of React to create interactive blog posts. - -::: - -{/* truncate */} - -For example, use JSX to create an interactive button: - -```js - -``` - - diff --git a/blog/_scripts/closures-state-retention.js b/blog/_scripts/closures-state-retention.js new file mode 100644 index 0000000..3be989b --- /dev/null +++ b/blog/_scripts/closures-state-retention.js @@ -0,0 +1,19 @@ +// 1. Create a function that establishes a private closure +function createToggle() { + // This variable is private and persists in memory + let state = false; + + // Return the inner function that remembers the 'state' variable + return function toggle() { + state = !state; + return state ? "ON 🟒" : "OFF πŸ”΄"; + }; +} + +// 2. Initialize the toggle instance +const buttonToggle = createToggle(); + +// 3. Run the experiment and log the retained state live +console.log("First click:", buttonToggle()); // Output: ON 🟒 +console.log("Second click:", buttonToggle()); // Output: OFF πŸ”΄ +console.log("Third click:", buttonToggle()); // Output: ON 🟒 diff --git a/blog/_scripts/variable-scoping-and-tdz.js b/blog/_scripts/variable-scoping-and-tdz.js new file mode 100644 index 0000000..844af35 --- /dev/null +++ b/blog/_scripts/variable-scoping-and-tdz.js @@ -0,0 +1,40 @@ +// ========================================== +// 1. OBJECT UPDATE CHECK +// ========================================== +const profile = { + username: "anonymous_coder" +}; + +profile.username = "JavaScript_Guru"; +console.log("Updated profile:", profile.username); + + +// ========================================== +// 2. BLOCK SCOPING CHECK +// ========================================== +if (true) { + var leakedVar = "I am leaked!"; + let scopedLet = "I am safe!"; +} + +// 'var' leaks because it is function/globally scoped, not block scoped +console.log("var access:", leakedVar); + +// 'let' safely throws an error because it belongs only to the 'if' block +try { + console.log("let access:", scopedLet); +} catch (err) { + console.log("Caught expected error:", err.message); +} + + +// ========================================== +// 3. TEMPORAL DEAD ZONE (TDZ) CHECK +// ========================================== +try { + // Accessing 'tdzVariable' before its declaration triggers the TDZ + console.log("Accessing let before declaration:", tdzVariable); + let tdzVariable = "I am successfully initialized!"; +} catch (err) { + console.log("Caught expected TDZ error:", err.message); +} \ No newline at end of file diff --git a/blog/demystifying-closures-and-lexical-scope.mdx b/blog/demystifying-closures-and-lexical-scope.mdx new file mode 100644 index 0000000..7e88f58 --- /dev/null +++ b/blog/demystifying-closures-and-lexical-scope.mdx @@ -0,0 +1,151 @@ +--- +slug: demystifying-closures-and-lexical-scope +title: "Demystifying Closures and Lexical Scope in JavaScript" +authors: [ajay-dhangar] +tags: [javascript, es6, web-development, intermediate, closures] +description: "Master closures and lexical scope in JavaScript. Learn how functions retain access to their outer variables, handle state encapsulation, and avoid memory leak pitfalls." +image: /img/blogs/closures-lexical-scope.png +date: 2026-09-08 +--- + +import JSEditor from "@site/src/components/js-live-code-editor"; +import CodeBlock from "@theme/CodeBlock"; +import firstExample from "!!raw-loader!./_scripts/closures-state-retention.js"; + +Closures are often regarded as one of JavaScript's most intimidating concepts, yet you likely use them every day without realizing it. Understanding closures unlocks powerful architectural patterns like data privacy, function currying, and custom event handlers. + +![Closures and Lexical Scope in JavaScript](/img/blogs/closures-lexical-scope.png) + +In this guide, we will break down **Lexical Scope**, how **Closures** preserve variable references across execution contexts, and real-world practical use cases. + + + +## What is Lexical Scope? + +JavaScript uses **Lexical Scoping** (also known as Static Scoping). This means that variable access is determined strictly by the physical location of code at compile/write timeβ€”not where functions are called at runtime. + +Nested inner functions always have access to variables declared in their outer parent scopes. + +```javascript +const globalName = "JavaScript Mastery"; + +function outerFunction() { + const outerVar = "I am outside!"; + + function innerFunction() { + // Has access to globalName, outerVar, and its own scope + console.log(`${globalName}: ${outerVar}`); + } + + innerFunction(); +} + +outerFunction(); // Logs: "JavaScript Mastery: I am outside!" + +``` + +## What is a Closure? + +A **Closure** is created when an inner function is returned or passed out of its parent scope, allowing it to "remember" and access variables from its outer lexical scope even **after the outer function has finished executing**. + +```javascript +function createCounter() { + let count = 0; // Private variable trapped inside closure + + return function increment() { + count++; + return count; + }; +} + +const counter = createCounter(); + +console.log(counter()); // 1 +console.log(counter()); // 2 +console.log(counter()); // 3 + +``` + +When `createCounter()` finishes running, its execution stack frame is popped off, but `count` remains stored in memory because `increment` retains a reference link to its outer lexical environment. + +## Practical Real-World Use Cases + +### 1. Data Privacy & Encapsulation (Private Variables) + +JavaScript classes natively support private fields (`#field`), but closures have historically provided robust encapsulation: + +```javascript +function createBankAccount(initialBalance) { + let balance = initialBalance; // Cannot be accessed directly from outside + + return { + deposit(amount) { + if (amount > 0) balance += amount; + return balance; + }, + withdraw(amount) { + if (amount <= balance) balance -= amount; + return balance; + }, + getBalance() { + return balance; + } + }; +} + +const account = createBankAccount(1000); +account.deposit(500); +console.log(account.getBalance()); // 1500 +console.log(account.balance); // undefined (Private state protected!) + +``` + +### 2. Function Currying & Partial Application + +Closures allow functions to accept arguments incrementally over multiple invocations: + +```javascript +const multiply = (a) => (b) => a * b; + +const double = multiply(2); +const triple = multiply(3); + +console.log(double(5)); // 10 +console.log(triple(5)); // 15 + +``` + +## Common Pitfalls: Memory Leaks + +Because closures retain references to outer scope variables, unreferenced large objects trapped inside closure scopes can lead to memory leaks if retained indefinitely. + +```javascript +// ❌ Potential Leak Pattern +function processData() { + const hugeArray = new Array(1000000).fill("Data"); + + return function logInfo() { + // Only needs length, but holds reference to full array context + console.log("Array ready"); + }; +} + +``` + +:::tip Mitigation Strategy +Extract only the primitive values or small fields required by the inner function rather than trapping large objects inside the outer function scope. +::: + +## Interactive Playground + +Experiment with private closures and state retention live: + + + {firstExample} + + +## Summary + +* **Lexical Scope** determines variable availability based on where code is written in the file. +* **Closures** pair a function with its surrounding lexical environment, allowing state retention across execution boundaries. +* **Key Applications** include module patterns, event handlers, function currying, and private variable encapsulation. \ No newline at end of file diff --git a/blog/var-let-const-scope-hoisting.mdx b/blog/var-let-const-scope-hoisting.mdx new file mode 100644 index 0000000..1841b03 --- /dev/null +++ b/blog/var-let-const-scope-hoisting.mdx @@ -0,0 +1,184 @@ +--- +slug: var-let-const-scope-hoisting +title: "Var, Let, or Const?" +authors: [ajay-dhangar] +tags: [javascript, es6, web-development, beginners, clean-code] +description: "Demystify variable declarations in JavaScript. Learn the critical differences between var, let, and const, block scope vs. function scope, hoisting, and the Temporal Dead Zone." +image: /img/blogs/var-let-const.svg +date: 2026-09-08 +--- + +import JSEditor from "@site/src/components/js-live-code-editor"; +import CodeBlock from "@theme/CodeBlock"; +import firstExample from "!!raw-loader!./_scripts/variable-scoping-and-tdz.js"; + +Understanding variable declarations is foundational to writing robust, bug-free JavaScript. Before ES6 (ECMAScript 2015), `var` was our only choice. Today, we have `let` and `const` and picking the wrong one can lead to silent errors, scope leaks, and unpredictable behavior. + +![Var, Let, or Const](/img/blogs/var-let-const.svg) + +In this guide, we will break down **scope**, **hoisting**, re-assignment rules, and the **Temporal Dead Zone (TDZ)** with visual mental models and interactive examples. + + + +## Quick Comparison Matrix + +Before diving into details, here is the cheat sheet comparing `var`, `let`, and `const`: + +| Feature | `var` | `let` | `const` | +| :--- | :--- | :--- | :--- | +| **Scope** | Function Scope | Block Scope | Block Scope | +| **Hoisting** | Yes (initialized as `undefined`) | Yes (uninitialized in TDZ) | Yes (uninitialized in TDZ) | +| **Re-declaration** | Allowed in same scope | Forbidden | Forbidden | +| **Re-assignment** | Allowed | Allowed | Forbidden | +| **Initialization** | Optional (`undefined`) | Optional (`undefined`) | **Required** at declaration | + +## Scope: Where Do Variables Live? + +**Scope** determines where your variables are accessible within your code execution context. + +### 1. Function Scope (`var`) + +Variables declared with `var` are scoped to the nearest enclosing **function**. They completely ignore block boundaries like `if` statements, `for` loops, or plain `{}` blocks. + +```javascript +function scopeExample() { + if (true) { + var message = "I am visible outside the if block!"; + } + console.log(message); // "I am visible outside the if block!" +} + +scopeExample(); + +``` + +:::caution The Classic `for` Loop Bug +Because `var` ignores block scope, loop counters bleed into outer functions: + +```javascript +for (var i = 0; i < 3; i++) { + setTimeout(() => console.log(i), 100); // Logs 3, 3, 3! +} + +``` + +::: + +### 2. Block Scope (`let` & `const`) + +`let` and `const` respect **Block Scope**. A block is any code enclosed within curly braces `{}`. + +```javascript +function blockExample() { + if (true) { + let secret = "Hidden in block"; + const apiKey = "12345-ABC"; + } + // ReferenceError: secret is not defined + console.log(secret); +} + +``` + +By switching the classic loop counter from `var` to `let`, each loop iteration gets its own fresh lexical binding: + +```javascript +for (let i = 0; i < 3; i++) { + setTimeout(() => console.log(i), 100); // Logs 0, 1, 2! +} + +``` + +## Hoisting & The Temporal Dead Zone (TDZ) + +**Hoisting** is JavaScript's default behavior of moving variable and function declarations to the top of their containing scope during the memory allocation creation phase. + +### How `var` Hoists + +When `var` is hoisted, it is automatically initialized with `undefined`: + +```javascript +console.log(user); // Output: undefined (No crash!) +var user = "Alex"; + +// How JavaScript interprets it: +// var user; +// console.log(user); +// user = "Alex"; + +``` + +### How `let` and `const` Hoist (The Temporal Dead Zone) + +`let` and `const` are also hoisted, but they remain **uninitialized**. The period between the start of the scope execution and the variable's declaration line is called the **Temporal Dead Zone (TDZ)**. + +Attempting to read a variable inside its TDZ triggers a runtime `ReferenceError`. + +```javascript +console.log(score); // ❌ ReferenceError: Cannot access 'score' before initialization +let score = 99; + +``` + +```text +Scope Start ──────────────────────────┐ + β”‚ Temporal Dead Zone (TDZ) + β”‚ Accessing 'score' here throws ReferenceError +let score = 99; ──────────────────────┴ Declaration & Initialization +console.log(score); // 99 (Safe access) + +``` + +## Mutability: `const` Does Not Mean Immutable! + +A common misconception is that `const` values are immutable (unchangeable). In reality, `const` only creates an **immutable binding** to a memory reference. + +### Primitives vs. Objects + +* **Primitive values** (`number`, `string`, `boolean`) assigned to `const` cannot be changed. +* **Objects and Arrays** assigned to `const` *can* have their properties mutated! + +```javascript +const user = { name: "Sarah", role: "Developer" }; + +// βœ… Valid: Mutating internal properties +user.role = "Lead Architect"; +user.age = 28; + +// ❌ Invalid: Re-assigning the reference itself +user = { name: "John" }; // TypeError: Assignment to constant variable. + +``` + +:::tip Freezing Objects +To prevent mutating properties inside an object, use `Object.freeze()`: + +```javascript +const config = Object.freeze({ theme: "dark" }); +config.theme = "light"; // Silently fails (or throws Error in Strict Mode) + +``` + +::: + +## Interactive Playground + +Test variable scoping and TDZ behaviors directly in your browser: + + + {firstExample} + + +## Best Practice Checklist + +Follow this simple rule of thumb for clean, maintainable modern JavaScript: + +1. **Default to `const`** for all variable declarations. +2. **Use `let`** only when you know a variable value will be re-assigned (e.g., loop counters, state flags). +3. **Avoid `var` entirely** in modern ES6+ codebases to eliminate scope bleeding and unexpected hoisting bugs. + +## Summary + +* **`var`** is function-scoped, hoisted as `undefined`, and allows re-declarations. +* **`let`** is block-scoped, hoisted inside the **TDZ**, and allows re-assignment. +* **`const`** is block-scoped, hoisted inside the **TDZ**, forbids re-assignment, but allows object property mutations. \ No newline at end of file diff --git a/docs/01-getting-started/introduction.md b/docs/01-getting-started/introduction.md index 5450ab8..bdf1f1d 100644 --- a/docs/01-getting-started/introduction.md +++ b/docs/01-getting-started/introduction.md @@ -91,13 +91,4 @@ console.log(`Hello, I am ${developerName} with Level ${experienceLevel} expertis :::success Next Steps Ready to dive deeper? Proceed to the next page to configure your local development environment and developer tools! -::: - - -``` -docs/ -└── 07-design-patterns-and-best-practices/ - β”œβ”€β”€ _category_.json - β”œβ”€β”€ design-patterns.md - └── clean-code-and-performance.md -``` \ No newline at end of file +::: \ No newline at end of file diff --git a/docs/07-design-patterns-and-best-practices/clean-code-and-performance.md b/docs/07-design-patterns-and-best-practices/clean-code-and-performance.md index e69de29..1855577 100644 --- a/docs/07-design-patterns-and-best-practices/clean-code-and-performance.md +++ b/docs/07-design-patterns-and-best-practices/clean-code-and-performance.md @@ -0,0 +1,173 @@ +--- +id: clean-code-and-performance +title: "Clean Code & Performance Optimization" +sidebar_label: Clean Code & Performance +sidebar_position: 2 +description: "Master clean code principles, DRY/KISS/SOLID patterns, defensive programming, memory leak prevention, and V8 engine performance optimization in JavaScript." +tags: [javascript, clean-code, performance, solid, memory-leaks, optimization, v8] +--- + +import JSEditor from "@site/src/components/js-live-code-editor"; +import CodeBlock from "@theme/CodeBlock"; +import firstExample from "!!raw-loader!../_scripts/debounce-throttle-optimization.js"; + +Writing high-quality JavaScript requires balancing readability, maintainability, and runtime efficiency. Clean code makes codebases maintainable, while performance optimization ensures smooth execution under heavy loads. + +## Clean Code Core Principles + +### 1. Meaningful Naming & Intent-Revealing Identifiers + +Variable and function names should clearly express intent without requiring explanatory comments. + +```javascript +// ❌ Poor Naming +const d = new Date(); +const u = getUsers(); +function process(x) { + return x.filter(i => i.a > 18); +} + +// βœ… Clean & Intent-Revealing +const currentDate = new Date(); +const activeUsers = getUsers(); +function getAdultUsers(userList) { + return userList.filter(user => user.age > 18); +} + +``` + +### 2. The SOLID Principles in JavaScript + +Applying SOLID design principles ensures modular, extensible software architecture: + +| Principle | Meaning | JavaScript Pattern | +| --- | --- | --- | +| **S** - Single Responsibility | A module/class should have only one reason to change | Separate data fetching from UI rendering | +| **O** - Open/Closed | Open for extension, closed for modification | Use Strategy Pattern / Polymorphism instead of giant `switch` statements | +| **L** - Liskov Substitution | Subtypes must be substitutable for their base types | Ensure subclasses maintain method parameter/return signatures | +| **I** - Interface Segregation | Prefer small, specific interfaces over large ones | Pass option objects with targeted properties rather than fat configuration objects | +| **D** - Dependency Inversion | Depend on abstractions, not concrete implementations | Inject dependencies into classes/functions via constructor parameters | + +```javascript +// βœ… Single Responsibility Principle (SRP) +class OrderManager { + calculateTotal(order) { + return order.items.reduce((sum, item) => sum + item.price, 0); + } +} + +class OrderRepository { + save(order) { + console.log(`Saving order ${order.id} to DB`); + } +} + +``` + +## Performance Optimization & Memory Management + +### 1. Common Memory Leaks & Solutions + +JavaScript uses automatic Garbage Collection (Mark-and-Sweep). However, memory leaks occur when references are accidentally retained: + +#### A. Forgotten Event Listeners & Timers + +Unremoved DOM listeners or active `setInterval` calls keep references in memory: + +```javascript +// ❌ Memory Leak +function attachTracker() { + const element = document.getElementById("button"); + setInterval(() => { + console.log("Tracking element:", element); + }, 1000); +} + +// βœ… Cleaned Reference +function attachTrackerSafe() { + const element = document.getElementById("button"); + const timerId = setInterval(() => { + if (!document.body.contains(element)) { + clearInterval(timerId); // Cleanup when DOM node is gone + return; + } + console.log("Tracking element:", element); + }, 1000); +} + +``` + +#### B. WeakMap & WeakSet for Automatic GC + +Use `WeakMap` or `WeakSet` when keys are DOM elements or object references to allow garbage collection when key objects are destroyed: + +```javascript +const metadataCache = new WeakMap(); + +function setElementMetadata(element, data) { + metadataCache.set(element, data); + // When 'element' is removed from DOM, its entry in metadataCache is auto-garbage collected +} + +``` + +### 2. V8 Engine Optimization Techniques + +1. **Keep Object Shapes Consistent**: Avoid dynamically deleting or re-ordering properties on hot objects. Inconsistent hidden classes (shapes) force V8 out of optimized inline caches. +2. **Prefer Monomorphic Functions**: Functions that consistently receive parameters of the exact same type run up to 10x faster due to V8 JIT compiler optimizations. +3. **Avoid Unnecessary Allocations inside Hot Loops**: Move object creation, array instantiations, and regex literals outside tight execution loops. + +## Interactive Playground: Debounce & Throttle Optimization + +Debouncing and throttling reduce function execution rates for high-frequency events (like `scroll`, `resize`, or `keyup` search handlers): + + + {firstExample} + + +## Best Practices + +1. **Fail Early with Defensive Guard Clauses**: Validate function preconditions immediately and return early to flatten nested conditionals. +2. **Favor Pure Functions**: Functions without side effects are easier to unit test, debug, memoize, and optimize. +3. **Audit Large Third-Party Dependencies**: Use tree-shaking and native ES APIs instead of loading monolithic utility libraries when simple native methods exist. + +## Knowledge Check + +### Exercise Requirements: + +Refactor the following messy function into clean code using guard clauses, early returns, and array helper methods: + +```javascript title="dirty-code.js" +function processUsers(users) { + let results = []; + if (users != null) { + if (users.length > 0) { + for (let i = 0; i < users.length; i++) { + if (users[i].isActive === true) { + results.push(users[i].name.toUpperCase()); + } + } + } + } + return results; +} + +``` + +```javascript title="solution.js" +function processUsers(users = []) { + // Defensive guard clause + if (!Array.isArray(users) || users.length === 0) { + return []; + } + + return users + .filter((user) => user?.isActive) + .map((user) => user.name.toUpperCase()); +} + +``` + +:::success Module Complete! +Congratulations! You have completed **Phase 07: Design Patterns & Best Practices**. You are ready for **Phase 08: Testing, Tooling & Production**! +::: \ No newline at end of file diff --git a/docs/07-design-patterns-and-best-practices/design-patterns.md b/docs/07-design-patterns-and-best-practices/design-patterns.md index e69de29..5112d38 100644 --- a/docs/07-design-patterns-and-best-practices/design-patterns.md +++ b/docs/07-design-patterns-and-best-practices/design-patterns.md @@ -0,0 +1,287 @@ +--- +id: design-patterns +title: "JavaScript Design Patterns" +sidebar_label: Design Patterns +sidebar_position: 1 +description: "Master modern Creational, Structural, and Behavioral design patterns in JavaScript, including Singleton, Factory, Observer, Module, and Strategy patterns." +tags: [javascript, design-patterns, architecture, singleton, factory, observer, strategy, clean-code] +--- + +import JSEditor from "@site/src/components/js-live-code-editor"; +import CodeBlock from "@theme/CodeBlock"; +import firstExample from "!!raw-loader!../_scripts/observer-pattern.js"; + +Design patterns are reusable solutions to commonly occurring problems in software design. In JavaScript, design patterns leverage features like closures, first-class functions, classes, and ES modules to build scalable, maintainable architectures. + +## Creational Patterns + +Creational patterns focus on object creation mechanisms, controlling how objects are instantiated to increase code flexibility and reuse. + +### 1. Singleton Pattern + +Ensures a class has only one instance and provides a global point of access to it. + +```javascript +class DatabaseConnection { + static #instance = null; + + constructor(connectionString) { + if (DatabaseConnection.#instance) { + return DatabaseConnection.#instance; + } + this.connectionString = connectionString; + this.isConnected = true; + DatabaseConnection.#instance = this; + } + + static getInstance(connectionString) { + if (!DatabaseConnection.#instance) { + DatabaseConnection.#instance = new DatabaseConnection(connectionString); + } + return DatabaseConnection.#instance; + } +} + +const db1 = new DatabaseConnection("mongodb://localhost:27017"); +const db2 = new DatabaseConnection("postgres://localhost:5432"); + +console.log(db1 === db2); // true (Both refer to the single instance) + +``` + +:::tip ES Modules as Singletons +In modern JavaScript, ES modules are naturally singletons because they are evaluated once and cached across imports. +::: + +### 2. Factory Pattern + +Provides an interface for creating objects without explicitly specifying their exact classes, delegating instantiation logic to subclasses or factory functions. + +```javascript +class User { + constructor(name, role) { + this.name = name; + this.role = role; + } +} + +class UserFactory { + static createUser(type, name) { + switch (type.toLowerCase()) { + case "admin": + return new User(name, "Admin (Full Access)"); + case "editor": + return new User(name, "Editor (Content Access)"); + default: + return new User(name, "Viewer (Read-Only)"); + } + } +} + +const admin = UserFactory.createUser("admin", "Alex"); +const viewer = UserFactory.createUser("viewer", "Jordan"); + +``` + +## Structural Patterns + +Structural patterns deal with object composition, identifying simple ways to realize relationships between entities. + +### 1. Observer Pattern (Pub/Sub) + +Defines a one-to-many dependency where changing one object automatically updates and notifies dependent observers. + +```javascript +class EventEmitter { + constructor() { + this.events = {}; + } + + on(event, listener) { + if (!this.events[event]) { + this.events[event] = []; + } + this.events[event].push(listener); + return () => this.off(event, listener); // Unsubscribe handler + } + + off(event, listenerToRemove) { + if (!this.events[event]) return; + this.events[event] = this.events[event].filter( + (listener) => listener !== listenerToRemove + ); + } + + emit(event, data) { + if (!this.events[event]) return; + this.events[event].forEach((listener) => listener(data)); + } +} + +// Usage +const store = new EventEmitter(); +const unsubscribe = store.on("cart:add", (item) => { + console.log(`Item added to cart: ${item.name}`); +}); + +store.emit("cart:add", { id: 1, name: "Mechanical Keyboard" }); +unsubscribe(); // Clean up listener + +``` + +### 2. Module Pattern + +Encapsulates private state and exposes a clean public API using closures or IIFEs (and natively via ES module scoping). + +```javascript +const CartModule = (() => { + // Private variables and functions + const items = []; + + function calculateTotal() { + return items.reduce((sum, item) => sum + item.price, 0); + } + + // Public interface + return { + addItem(item) { + items.push(item); + }, + getTotal() { + return calculateTotal(); + }, + getItemCount() { + return items.length; + } + }; +})(); + +CartModule.addItem({ name: "Monitor", price: 300 }); +console.log(CartModule.getTotal()); // 300 +// items array remains inaccessible from outside + +``` + +## Behavioral Patterns + +Behavioral patterns manage algorithms, responsibilities, and communication between objects. + +### 1. Strategy Pattern + +Encapsulates interchangeable algorithms inside objects so they can be swapped dynamically at runtime without altering client logic. + +```javascript +// Strategies +const PaymentStrategies = { + creditCard: (amount) => `Paid $${amount} via Credit Card (2% fee)`, + paypal: (amount) => `Paid $${amount} via PayPal (1% fee)`, + crypto: (amount) => `Paid $${amount} via Crypto (0% fee)` +}; + +// Context +class Checkout { + constructor(strategy = PaymentStrategies.creditCard) { + this.strategy = strategy; + } + + setStrategy(strategy) { + this.strategy = strategy; + } + + processOrder(amount) { + return this.strategy(amount); + } +} + +const checkout = new Checkout(PaymentStrategies.paypal); +console.log(checkout.processOrder(100)); // Paid $100 via PayPal (1% fee) + +checkout.setStrategy(PaymentStrategies.crypto); +console.log(checkout.processOrder(100)); // Paid $100 via Crypto (0% fee) + +``` + +## Interactive Playground: Observer Pattern + +Observe event driven subscription management in interactive code execution: + + + {firstExample} + + +## Best Practices + +1. **Avoid Over-Engineering**: Do not implement design patterns preemptively. Apply them when code complexity or duplication warrants structural refactoring. +2. **Favor Composition Over Inheritance**: Patterns like Strategy and Decorator favor flexible composition instead of deep class inheritance hierarchies. +3. **Use Native ES Constructs**: Modern features like ES Modules, Private Fields (`#`), and `Proxy` objects fulfill many pattern goals out-of-the-box. + +## Knowledge Check + +### Exercise Requirements: + +Implement a `CommandPattern` interface with an `Invoker`, an `Execute` method, and an `Undo` method for managing text editor actions (such as adding and removing text). + +```javascript title="solution.js" +class TextEditor { + constructor() { + this.content = ""; + } + + append(text) { + this.content += text; + } + + delete(length) { + this.content = this.content.slice(0, -length); + } +} + +class AppendCommand { + constructor(editor, textToAppend) { + this.editor = editor; + this.text = textToAppend; + } + + execute() { + this.editor.append(this.text); + } + + undo() { + this.editor.delete(this.text.length); + } +} + +class CommandHistory { + constructor() { + this.history = []; + } + + execute(command) { + command.execute(); + this.history.push(command); + } + + undo() { + const command = this.history.pop(); + if (command) { + command.undo(); + } + } +} + +// Usage +const editor = new TextEditor(); +const history = new CommandHistory(); + +history.execute(new AppendCommand(editor, "Hello ")); +history.execute(new AppendCommand(editor, "World!")); +console.log(editor.content); // "Hello World!" + +history.undo(); +console.log(editor.content); // "Hello " + +``` + +:::success Next Up +Now that you have mastered JavaScript Design Patterns, proceed to **Clean Code & Refactoring**! +::: \ No newline at end of file diff --git a/docs/_scripts/debounce-throttle-optimization.js b/docs/_scripts/debounce-throttle-optimization.js new file mode 100644 index 0000000..4308f6f --- /dev/null +++ b/docs/_scripts/debounce-throttle-optimization.js @@ -0,0 +1,23 @@ +function debounce(fn, delay) { + let timeoutId; + + return function (...args) { + // Clear the previous timer if the function is called again before the delay finishes + clearTimeout(timeoutId); + + // Set a new timer to execute the function after the specified delay + timeoutId = setTimeout(() => { + fn(...args); + }, delay); + }; +} + +// Create the debounced search function +const handleSearch = debounce((query) => { + console.log("Triggering API search for:", query); +}, 300); + +// Simulating fast user keystrokes +handleSearch("J"); +handleSearch("Java"); +handleSearch("JavaScript"); // Only this final call executes after 300ms! \ No newline at end of file diff --git a/docs/_scripts/fibonacci-gen.js b/docs/_scripts/fibonacci-gen.js index 81bc911..6f58416 100644 --- a/docs/_scripts/fibonacci-gen.js +++ b/docs/_scripts/fibonacci-gen.js @@ -22,4 +22,4 @@ for (const value of fibGen) { } // Print the final array as a comma-separated string -console.log("Fibonacci Sequence (7 items):", results.join(", ")); +console.log("Fibonacci Sequence (7 items):", results.join(", ")); \ No newline at end of file diff --git a/docs/_scripts/observer-pattern.js b/docs/_scripts/observer-pattern.js new file mode 100644 index 0000000..28dce81 --- /dev/null +++ b/docs/_scripts/observer-pattern.js @@ -0,0 +1,21 @@ +class Subject { + constructor() { + this.observers = []; + } + + subscribe(fn) { + this.observers.push(fn); + } + + notify(data) { + this.observers.forEach((fn) => fn(data)); + } +} + +const newsFeed = new Subject(); + +// Register multiple observers +newsFeed.subscribe((news) => console.log("[UI Banner]:", news)); +newsFeed.subscribe((news) => console.log("[Push Notification]:", news)); + +newsFeed.notify("ES2026 Features Officially Released!"); \ No newline at end of file diff --git a/static/img/blogs/closures-lexical-scope.png b/static/img/blogs/closures-lexical-scope.png new file mode 100644 index 0000000000000000000000000000000000000000..61565b9c86b4594ca24196b489269814e31bdfba GIT binary patch literal 11463 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 YRMEe!{|RvZFRxfhUQMoC#_Zew0jsb7egFUf literal 0 HcmV?d00001 diff --git a/static/img/blogs/var-let-const.svg b/static/img/blogs/var-let-const.svg new file mode 100644 index 0000000..80c2ab4 --- /dev/null +++ b/static/img/blogs/var-let-const.svg @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + JS + + + JAVASCRIPT MASTERY + var vs. let vs. const + + + + + var + β€’ Function Scoped + β€’ Hoisted (undefined) + β€’ Re-declarable + β€’ Re-assignable + + + + + let + β€’ Block Scoped + β€’ Temporal Dead Zone + β€’ No Re-declaration + β€’ Re-assignable + + + + + const + β€’ Block Scoped + β€’ Temporal Dead Zone + β€’ Fixed Binding + β€’ Mutable Properties +