โ””โ”€โ”€ README.md /README.md: -------------------------------------------------------------------------------- 1 | # Table of Contents 2 | 3 | 1. [JavaScript: Getting Started ๐Ÿ”ฅ](#javascript-getting-started-) 4 | 2. [JavaScript: Data types and variables ๐Ÿ”ฅ](#javascript-data-types-and-variables-) 5 | 3. [JavaScript: Execution Context โญ](#javascript-execution-context-) 6 | 4. [JavaScript Hoisting - Explained EASILY](#javascript-hoisting---explained-easily) 7 | 5. [JavaScript: Function Declaration vs Function Expression and Much More๐Ÿ”ฅ](#javascript-function-declaration-vs-function-expression-and-much-more) 8 | 6. [JavaScript: undefined vs Not defined๐Ÿ”ฅ](#javascript-undefined-vs-not-defined) 9 | 7. [JavaScript: Scope and Lexical Scope ๐Ÿ”ฅ](#javascript-scope-and-lexical-scope-) 10 | 8. [JavaScript: Types of Errors ๐Ÿคก](#javascript-types-of-errors-) 11 | 9. [JavaScript: Block Scope & Shadowing๐Ÿ”ฅ](#javascript-block-scope--shadowing) 12 | 10. [JavaScript: Closures ๐Ÿ”ฅ](#javascript-closures-) 13 | 11. [JavaScript: Callback Functions ๐Ÿ”ฅ](#javascript-callback-functions-) 14 | 12. [JavaScript: Working of Async Code ๐Ÿ”ฅ](#javascript-working-of-async-code-) 15 | 13. [How JavaScript Engine Works ๐Ÿš‚๐Ÿ’จ](#how-javascript-engine-works-) 16 | 14. [JavaScript: Callbacks Problems ๐Ÿ”ฅ](#javascript-callbacks-problems-) 17 | 15. [JavaScript: Promises ๐Ÿ”ฅ](#javascript-promises-) 18 | 16. [JavaScript: Promise APIs ๐Ÿ”ฅ๐Ÿ”ฅ](#javascript-promise-apis-) 19 | 17. [JavaScript: Async/Await ๐Ÿ”ฅ](#javascript-asyncawait-) 20 | 18. [JavaScript: `this` keyword ๐Ÿ”ฅ](#javascript-this-keyword-) 21 | 19. [JavaScript: "use strict" ๐Ÿ”ฅ](#javascript-use-strict-) 22 | 20. [JavaScript: call(), apply(), bind() ๐Ÿ”ฅ](#javascript-call-apply-bind-) 23 | 21. [JavaScript: Currying ๐Ÿ› ๐Ÿ”ฅ](#javascript-currying--) 24 | 22. [JavaScript: Prototype ๐Ÿ”ฅ๐Ÿ”ฅ](#javascript-prototype-) 25 | 23. [JavaScript: OOP Introduction๐Ÿ”ฅ](#javascript-oop-introduction) 26 | 24. [JavaScript: Inheritance ๐Ÿ”ฅ๐Ÿ‘จโ€๐Ÿ‘ฆ](#javascript-inheritance-) 27 | 25. [JavaScript: Abstraction and Encapsulation ๐Ÿ”ฅ](#javascript-abstraction-and-encapsulation-) 28 | 26. [JavaScript: Static Properties and Methods ๐Ÿ”ฅ](#javascript-static-properties-and-methods-) 29 | 27. [JavaScript: Event Bubbling & Capturing ๐Ÿ”ฅ](#javascript-event-bubbling--capturing-) 30 | 28. [JavaScript: Event Delegation ๐Ÿ”ฅ](#javascript-event-delegation-) 31 | 29. [JavaScript: Script Loading ๐Ÿ”ฅ](#javascript-script-loading-) 32 | 30. [JavaScript: Coercion ๐Ÿ”ฅ๐Ÿ”ฅ๐Ÿ”ฅ](#javascript-coercion-) 33 | 31. [JavaScript: Coercion Day 2 ๐Ÿ”ฅ๐Ÿ”ฅ](#javascript-coercion-day-2-) 34 | 32. [JavaScript: Coercian Day 3 ๐Ÿ”ฅ๐Ÿ”ฅ](#javascript-coercian-day-3-) 35 | 33. [JavaScript: Coercion Last Day ๐Ÿ”ฅ๐Ÿ”ฅ๐Ÿ”ฅ](#javascript-coercion-last-day-) 36 | 34. [JavaScript: == ๐Ÿ†š ===](#javascript---) 37 | 35. [JavaScript: NaN (Not a Number) ๐Ÿฅต](#javascript-nan-not-a-number-) 38 | 36. [Debouncing and Throttling ๐Ÿ”ฅ](#-debouncing-and-throttling-) 39 | 37. [How to loop over objects? ๐Ÿค”๐Ÿ‘€](#how-to-loop-over-objects-) 40 | 41 | 42 | # JavaScript: Getting Started ๐Ÿ”ฅ 43 | 44 | ## Introduction to ECMAScript 45 | 46 | Before diving into JavaScript, let's get acquainted with ECMAScript, the standard on which JavaScript is based. 47 | 48 | ### Versions of ECMAScript 49 | 50 | - **ES1** - 1997 (First release) 51 | - โญ **ES6** - 2015 (Major changes introduced) 52 | - **ES13** - 2022 (Latest version) 53 | 54 | ## What is JavaScript? 55 | 56 | JavaScript is a versatile scripting language primarily used for web development. Here's a brief overview: 57 | 58 | - **Purpose**: Used to add interactivity and dynamic effects to web pages. 59 | - **File Extension**: `.js` 60 | - **Usage**: Initially designed for client-side development, but now also used in server-side development. 61 | - **Typing**: Dynamically typed (no need to specify data types). 62 | - **Concurrency Model**: Asynchronous single-threaded language. 63 | 64 | ### Frameworks and Libraries 65 | 66 | - **Frontend Frameworks**: React, Angular, Vue, etc. 67 | - **Backend Frameworks**: Express, Node.js 68 | 69 | ## JavaScript Engine 70 | 71 | To run JavaScript, we need a JavaScript engine that executes and compiles JS into native machine code. 72 | 73 | ### Common JavaScript Engines 74 | 75 | - **Chrome**: V8 76 | - **Firefox**: SpiderMonkey 77 | - **Safari**: JavaScriptCore 78 | - **Edge (IE)**: Chakra 79 | 80 | ## Running JavaScript Outside the Browser 81 | 82 | JavaScript can be executed outside the browser using Node.js. 83 | 84 | ### Node.js 85 | 86 | Node.js is an open-source, cross-platform JavaScript runtime environment that executes JavaScript code outside of a web browser. It's commonly used for: 87 | 88 | - Server-side applications 89 | - Command-line tools 90 | - Scalable network programs 91 | 92 | --- 93 | 94 | This guide provides a brief introduction to JavaScript and its related technologies. For a deeper dive, consider exploring each topic in more detail. 95 | 96 | # JavaScript: Data types and variables ๐Ÿ”ฅ 97 | 98 | Variables are like a container that store some data. 99 | 100 | In JavaScript we can declare variables in three ways that is using var, let, and const. 101 | 102 | General Rules for variable names: 103 | - cannot start with a number 104 | - names are case sensitive 105 | - names can only contains letters, digits and underscores _ 106 | 107 | 108 | 109 | ## Data Types 110 | 111 | In JavaScript we can classify data types in two types 112 | 113 | 1. Primitive Data Types [ simple ] 114 | - Numbers 115 | - Strings 116 | - Booleans 117 | - Null 118 | - Undefined 119 | - Big Int 120 | - Symbol 121 | 122 | 2. Objects: 123 | - Object stores data in key-value pairs 124 | - They are mutable (can be modified) 125 | - Considered as complex Data structure 126 | [ Example: Object, Array, Date Object ] 127 | 128 | 129 | ## ๐Ÿ”ฅ var vs let vs const ๐Ÿ”ฅ 130 | 131 | **var** 132 | - introduced in early days 133 | - limitations: it is function scoped not block scoped 134 | 135 | Means - variables are accessible within entire function in which they are declared, rather than just within the block of code they appear 136 | 137 | 138 | **let** 139 | - introduced in es6 140 | - block scoped 141 | - value can be reassigned 142 | 143 | **const** 144 | - introduced in es6 145 | - block scoped 146 | - value can not be reassigned 147 | - must assign value while declaration 148 | 149 | ![image](https://github.com/Tapesh-1308/linkedin-js-series/assets/71540051/e93073d8-1e74-4b8b-825e-077486db236e) 150 | 151 | 152 | # JavaScript: Execution Context โญ 153 | 154 | When the JS engine scans code, it creates an environment called the Execution Context. 155 | 156 | ## Types of Execution Context 157 | 158 | 1. **Global EC**: Created when JS code first starts to run and represents the global scope in JS. 159 | 2. **Function EC**: Created when a function in the code starts executing. 160 | 161 | ## Execution Phases 162 | 163 | ### 1. Memory Creation Phase 164 | - Allocates location to variables and functions. 165 | - Stores variables with value as `undefined` and function references (i.e., the complete function definition). 166 | 167 | ### 2. Execution Phase 168 | - Starts through the entire code line by line. 169 | - Assigns values to variables in memory. 170 | - For functions, when invoked, JS creates a new function EC. 171 | - When a function returns a value, the function EC is destroyed. 172 | 173 | *Once the entire code execution is done, the Global EC will be destroyed as well.* 174 | 175 | ## Call Stack (Last In First Out) 176 | 177 | - To keep track of contexts, JS uses a call stack. 178 | - A call stack has a fixed size depending on the system or browser. 179 | - Exceeding the size limit causes a stack overflow error. 180 | 181 | We will explore more about scopes and how the JS engine works internally in later posts. So stay tuned โœจ 182 | 183 | 184 | ![image](https://github.com/Tapesh-1308/linkedin-js-series/assets/71540051/8b0d3621-23f0-42bc-96ed-5edccafe6e17) 185 | 186 | 187 | # JavaScript Hoisting - Explained EASILY 188 | 189 | ## Prerequisite 190 | - JavaScript Execution Process 191 | - Basic knowledge of Scope 192 | 193 | Hoisting is a behavior in JavaScript where all declarations of a function, variable, or class go to the top of the scope they are defined in. 194 | 195 | This whole process is done during the Memory Creation Phase. 196 | Let's see what actually happens with: 197 | 198 | ### Variables 199 | - **`var`**: Variables are hoisted but with a default value of `undefined`. 200 | - **`let` and `const`**: Hoisted but inaccessible before default initialization. [Gives Error when accessed before initialization] 201 | 202 | ### Functions 203 | Functions become accessible even before the line they are declared. Hoisting does not occur in function expressions, it occurs only in function declarations. 204 | 205 | ### Point to Note 206 | - Hoisting happens based on the scope. It sets variables and functions to the top of the scope. 207 | 208 | ### Related Topic: Temporal Dead Zone 209 | - Area where variables are hoisted but inaccessible until they are initialized with a value. [Applies to `let` and `const`, not to `var`] 210 | 211 | 212 | ## From where I learned Hoisting? 213 | - Watch this video: [Akshay Saini's video](https://lnkd.in/gfdGax5P) ๐Ÿš€ 214 | - Read this freeCodeCamp Article: [freeCodeCamp Article](https://lnkd.in/gyP6Qc_s) 215 | 216 | 217 | ![image](https://github.com/Tapesh-1308/linkedin-js-series/assets/71540051/e9a100aa-0f0c-4d3b-a95a-510a1d33d18f) 218 | 219 | 220 | # JavaScript: Function Declaration vs Function Expression and Much More๐Ÿ”ฅ 221 | 222 | ## Function Declaration (aka function statement) ๐Ÿ‘€ 223 | 224 | - Named function where you declare a name after the `function` keyword. 225 | 226 | Example: 227 | ```javascript 228 | function myFunc() { 229 | // function body 230 | } 231 | ``` 232 | 233 | ## Function Expression ๐Ÿ‘€ 234 | 235 | - Anonymous functions, where we use the `function` keyword without a name, then assign it to a variable. 236 | 237 | Example: 238 | ```javascript 239 | const myFunc = function () { 240 | // function body 241 | }; 242 | ``` 243 | 244 | * Here you can use `var` or `let` as well. 245 | - If `var` is used, it will store `undefined` in the memory creation phase. 246 | - If `let` and `const` are used, it will throw an error: we cannot access them before initialization. 247 | 248 | ### Function Expression (Benefits and Drawbacks) 249 | - Cannot be accessed before initialization. 250 | - Needs to be assigned to be used later. 251 | - Anonymous functions are useful for anonymous operations, e.g., IIFEs, callback functions, etc. 252 | 253 | We can also have named function expressions like this: 254 | 255 | ```javascript 256 | const print = function x() { 257 | // function body 258 | }; 259 | ``` 260 | But here `x` is not accessible. 261 | 262 | ## Common Confusion: Parameters and Arguments 263 | 264 | - **Parameters**: In function definition. 265 | ```javascript 266 | function myFunc(param1, param2) { 267 | // function body 268 | } 269 | ``` 270 | 271 | - **Arguments**: While calling functions. 272 | ```javascript 273 | let sum = add(arg1, arg2); 274 | ``` 275 | 276 | ## First Class Functions / Citizens 277 | 278 | - Ability to use functions like values. 279 | 280 | In JavaScript, we can: 281 | - Assign a function to a variable. 282 | - Pass a function as an argument. 283 | - Return a function from another function. 284 | 285 | So, JavaScript functions are first class ๐Ÿ”ฅ 286 | 287 | # JavaScript: undefined vs Not defined๐Ÿ”ฅ 288 | 289 | ## Undefined 290 | - Predefined global variable that represents the value assigned to a variable during the memory creation phase. 291 | 292 | ## Not defined 293 | - Means the variable has not been declared at all. Accessing such a variable results in a reference error. 294 | 295 | ## Sum up ๐Ÿ’ช 296 | A variable that has been declared but not assigned a value is `undefined`, and a variable that has not been declared at all is `not defined`. 297 | 298 | 299 | ![image](https://github.com/Tapesh-1308/linkedin-js-series/assets/71540051/f8223be8-8560-4b44-830d-e2e6f783a362) 300 | 301 | 302 | # JavaScript: Scope and Lexical Scope ๐Ÿ”ฅ 303 | 304 | ## Disclaimer โš  305 | This post is content-heavy. 306 | 307 | ## Scope 308 | - Area where an item (variable or function) is visible and accessible to other code. 309 | 310 | ## Lexical Scope (Static Scope) 311 | - A place where all the variables and functions of a parent lie. This scope is passed to the children scope (nested scope). 312 | 313 | Consider this code and call stack: 314 | 315 | ```javascript 316 | let name = "Tapesh"; 317 | function a() { 318 | function b() { 319 | function c() { 320 | console.log(name); 321 | } 322 | c(); 323 | } 324 | b(); 325 | } 326 | a(); 327 | ``` 328 | 329 | ### Call Stack 330 | ``` 331 | | C() | 332 | | B() | 333 | | A() | 334 | | GEC | 335 | |-----| 336 | ``` 337 | 338 | ### Explanation 339 | 340 | - `C()` has access to variables and functions in its own scope + lexical scope of its parent (`B()`). 341 | - `B()` has access to its own scope + lexical scope of its parent (`A()`). 342 | - `A()` has access to its own scope + lexical scope of its parent (Global Execution Context). 343 | - Global Execution Context (GEC) has access to its own scope + parent (since it has no parent, it points to `null`). 344 | 345 | ## Scope Chain โ›“ 346 | 347 | - Determines the hierarchy where JS code must go through to find the lexical scope (origin) of a specific variable. 348 | 349 | As in the above example: 350 | - Code first finds the `name` variable in `C`'s scope. 351 | - If not found, it goes to its lexical scope (that is `B`'s scope). 352 | - If not found, it goes to `A`'s scope. 353 | - If not found, it goes to GEC (found โœ”). 354 | - If not found, it returns a "not defined" error. 355 | 356 | ### Chain 357 | C -> B -> A -> GEC 358 | 359 | 360 | ![image](https://github.com/Tapesh-1308/linkedin-js-series/assets/71540051/85288d8a-8ee7-4c48-a7d7-cd108540f62c) 361 | 362 | 363 | # JavaScript: Types of Errors ๐Ÿคก 364 | 365 | Three types of errors you can see in JavaScript: 366 | 367 | ## Reference Errors 368 | 369 | When you attempt to use a variable (or a reference) that has not been declared. 370 | 371 | - Accessing undeclared variables. 372 | - Accessing a variable outside of its scope. 373 | 374 | ## Syntax Errors (no line executes in this case) 375 | 376 | When code does not conform to the structure or syntax rules of the JavaScript language. 377 | 378 | - Incorrect use of language constructs. 379 | - Missed or extra punctuations. 380 | 381 | ## Type Errors 382 | 383 | When an operation is performed on a value of an unexpected type. 384 | 385 | - Trying to call a function that is not a function. 386 | - Accessing properties or methods of `null` and `undefined`. 387 | 388 | ## Can You Answer This Question? ๐Ÿ‘‡ 389 | 390 | Which type of error will this snippet give? 391 | 392 | ```javascript 393 | function testFunction() { 394 | console.log(answer); 395 | } 396 | 397 | testFunction(); 398 | ``` 399 | 400 | ![image](https://github.com/Tapesh-1308/linkedin-js-series/assets/71540051/8473a158-0c01-4ebd-a19c-e3bdaac08753) 401 | 402 | 403 | # JavaScript: Block Scope & Shadowing๐Ÿ”ฅ 404 | 405 | ## Topics Covered 406 | - Block 407 | - Block Scope 408 | - Shadowing 409 | - Illegal Shadowing 410 | 411 | ## What is a Block? (compound statement) 412 | A block is defined by curly braces `{...}`. 413 | - Used to combine multiple JavaScript statements into one group. 414 | - We can use it where JavaScript expects one single statement. 415 | 416 | **Example:** 417 | ```javascript 418 | if (true) { 419 | // block 420 | } 421 | ``` 422 | 423 | ## Block Scoped 424 | - Scope in which we can access all variables and functions of that block. Lexical scope also works here. 425 | 426 | **Note:** 427 | - `let` and `const` are block scoped, meaning they cannot be accessed outside the block. 428 | - `var` is globally scoped. 429 | 430 | ## Shadowing 431 | - If we have the same named variable outside the block, then the block variable shadows the outside variable. 432 | 433 | **Example:** 434 | ```javascript 435 | let a = 1; // shadowed 436 | { 437 | let a = 2; 438 | console.log(a); // 2 439 | } 440 | ``` 441 | 442 | Because `let` and `const` variables are stored in different memory locations: in the block object for block variables, and in the script object for global variables. 443 | 444 | **In short:** 445 | - Global: reserved for `var` 446 | - Script: for `let` and `const` (outside block) 447 | - Block: separate memory for variables (`let` and `const`) inside scope 448 | 449 | ## Illegal Shadowing 450 | - When an outside variable is declared with `let` or `const`, but inside the block, it is declared with `var`. 451 | - If a variable is shadowing any outside variable, it should not cross the boundary of its scope. 452 | 453 | **Example:** 454 | ```javascript 455 | let a = 10; 456 | { 457 | var a = 20; // illegal shadowing 458 | } 459 | ``` 460 | 461 | However: 462 | ```javascript 463 | var a = 10; 464 | { 465 | let a = 20; // works fine since let creates a separate block 466 | } 467 | ``` 468 | 469 | ![image](https://github.com/Tapesh-1308/linkedin-js-series/assets/71540051/95a090ff-571b-4f70-aaa9-e667bd519874) 470 | 471 | 472 | # JavaScript: Closures ๐Ÿ”ฅ 473 | 474 | A closure is the combination of a function bundled together with a reference to its lexical environment. 475 | 476 | In JavaScript, a closure is a function that remembers its outer variables and can access them even when called independently. 477 | 478 | ## Advantages 479 | - Data handling / encapsulation 480 | - State retention 481 | - Currying (will study later) 482 | - Memoization 483 | - Asynchronous programming 484 | - Event handling 485 | 486 | ## Disadvantages 487 | - Variables declared inside a closure are not garbage collected. 488 | - Garbage collection is done when function execution gets completed. All the variables are deleted from memory. 489 | - Too many closures can slow down your application, caused by duplication of code in memory. 490 | 491 | 492 | ![image](https://github.com/Tapesh-1308/linkedin-js-series/assets/71540051/702be480-b25b-4164-adfc-5f6c8c10489b) 493 | 494 | 495 | # JavaScript: Callback Functions ๐Ÿ”ฅ 496 | 497 | ## Callback Functions 498 | 499 | In JavaScript, callback functions are functions passed as arguments to another function, enabling asynchronous behavior. 500 | 501 | ### Need of Callback Functions 502 | 503 | - **Asynchronous JavaScript**: Callback functions aid in the development of asynchronous JavaScript code. 504 | - **Execution Control**: Ensures that a function does not execute until a specific task is completed, but rather runs immediately after task completion. 505 | 506 | ### Usage 507 | 508 | 1. **Event Handling**: Callback functions are commonly used for event handling. 509 | 2. **Web APIs**: Utilized with functions such as `setTimeout` or `setInterval`. 510 | 3. **Data Fetching**: In scenarios like fetching data from external sources. 511 | 512 | See the image below for visual representation: 513 | 514 | 515 | ### Tips 516 | 517 | - **Event Listener Optimization**: Removing event listeners when not in use can optimize memory usage, preventing potential slowdowns on websites. 518 | 519 | 520 | ![image](https://github.com/Tapesh-1308/linkedin-js-series/assets/71540051/d650af8e-30ae-451b-a315-f158e8b9f233) 521 | 522 | 523 | # JavaScript: Working of Async Code ๐Ÿ”ฅ 524 | 525 | ## Prerequisite: Callback Function 526 | 527 | ### Blocking ๐Ÿ”ฅ 528 | 529 | - When tasks that take a lot of time (e.g., API calls, image processing) are executed in the main thread, they block the call stack or main thread until completion. 530 | - **Issue**: Blocking the main thread can lead to performance issues. 531 | 532 | **Solution**: Async Callbacks 533 | 534 | ### Process of Execution ๐Ÿ”ฅ 535 | 536 | 1. All callbacks are registered in the Web API with their attached timer and event. 537 | 2. Meanwhile, other code continues to execute. 538 | 3. When the timer expires or the callback is ready, it is pushed to the task queue but is not executed immediately. 539 | 540 | ### Event Loop ๐Ÿ” 541 | 542 | - The event loop checks if the call stack is empty. 543 | - If empty, it looks into the microtask queue and task queue for pending callbacks. 544 | - If a pending callback exists, the event loop pushes it to the top of the call stack for execution. 545 | 546 | ### Microtask Queue ๐Ÿ”ฅ 547 | 548 | - Introduced in ES6. 549 | - Used for promises and MutationObserver (changes in the DOM tree). 550 | - Has higher priority than the task queue. 551 | - The task queue must wait until the microtask queue is empty. 552 | 553 | ### Starvation of Task Queue ๐Ÿด 554 | 555 | - Occurs when resolved promises keep adding to the microtask queue, preventing the task queue callbacks from executing. 556 | - This can delay task queue callbacks indefinitely. 557 | 558 | ### Note 559 | 560 | During Event Listener usage, the original callback remains in the Web API environment indefinitely because the event may occur again. Therefore, it is recommended to remove listeners when not in use to allow the garbage collector to free up memory. 561 | 562 | ### FAQs 563 | 564 | **Q. When does the Event Loop actually start?** 565 | 566 | **A.** The event loop is always running and doing its job. 567 | 568 | **Q. Are only async callbacks registered in the Web API?** 569 | 570 | **A.** Yes, only async code moves to the Web API. 571 | 572 | **Q. Does the Web API store only callback functions and push the same to the queue?** 573 | 574 | **A.** Yes, callback functions are stored and a reference is scheduled in queues. 575 | 576 | **Q. What if `setTimeout` delay is 0 ms?** 577 | 578 | **A.** Even with a 0 ms delay, the callback goes through the whole process and waits for the call stack to be empty. 579 | 580 | 581 | ![image](https://github.com/Tapesh-1308/linkedin-js-series/assets/71540051/9d95bfb4-44b5-46a8-bd41-eec2a9ea8ea9) 582 | 583 | 584 | # How JavaScript Engine Works ๐Ÿš‚๐Ÿ’จ 585 | 586 | A browser has two main components: 587 | - **JavaScript Engine** 588 | - **Rendering Engine** 589 | 590 | ### JavaScript Engine 591 | 592 | The JavaScript Engine executes and compiles JavaScript into native machine code. 593 | 594 | - **Chrome**: v8 ๐Ÿ”ป 595 | - **Firefox**: SpiderMonkey ๐Ÿ’ 596 | - **Safari**: JavaScriptCore ๐Ÿ’ฅ 597 | - **Edge (IE)**: Chakra โœณ๏ธ 598 | 599 | ### Rendering Engine 600 | 601 | The Rendering Engine is responsible for rendering DOM trees, styles, events, etc. It paints the content on your screen. 602 | 603 | ### JS Engine Architecture 604 | 605 | - **Not a machine**: It's a program written in a low-level language. 606 | - **Function**: Takes high-level code (JavaScript) and converts it into machine-level code. 607 | 608 | #### Three MAIN steps to execute the code: 609 | 610 | 1. **Parsing** 611 | 2. **Compilation** 612 | 3. **Execution** 613 | 614 | ### 1. Parsing 615 | 616 | - **Process**: Reads code line by line. 617 | - **Steps**: 618 | 1. Breaks down code into tokens. 619 | 2. Passes tokens to a syntax parser. 620 | 621 | **Syntax Parser**: Converts the code into an AST (Abstract Syntax Tree). 622 | 623 | **AST**: Represents code as a tree-like structure. 624 | 625 | ### 2. Compilation 626 | 627 | JavaScript uses JIT (Just-In-Time) compilation, involving both an interpreter and a compiler. 628 | 629 | - **Process**: 630 | 1. AST goes to the interpreter (converted to high-level code). 631 | 2. Byte code then goes for execution. 632 | 633 | During step 1, the compiler helps optimize the code at runtime. 634 | 635 | ### 3. Execution 636 | 637 | Execution is not possible without the memory heap and call stack. 638 | 639 | - **Memory Heap**: Where all variables and functions are assigned to memory. It also includes a garbage collector to free up memory space whenever possible. 640 | 641 | **Garbage Collector**: Uses the mark-and-sweep algorithm to free up memory. ๐Ÿšฎ 642 | 643 | ### Note 644 | 645 | All browsers work differently, but the above steps are used by v8 and most engines work similarly. 646 | 647 | 648 | ![image](https://github.com/Tapesh-1308/linkedin-js-series/assets/71540051/9cb6935c-2512-45ed-8fe9-efafbaf1c629) 649 | 650 | 651 | # JavaScript: Callbacks Problems ๐Ÿ”ฅ 652 | 653 | ### Mainly two problems with callbacks: 654 | 655 | 1. **Callback Hell** 656 | 2. **Inversion of Control** 657 | 658 | ### 1. Callback Hell โ˜ ๏ธ 659 | 660 | Callback hell occurs when multiple callbacks are nested within a function. 661 | 662 | - The shape of the code resembles a pyramid ("pyramid of doom"). 663 | - This makes the code difficult to maintain and understand. 664 | 665 | ### 2. Inversion of Control ๐Ÿคธ๐Ÿปโ€โ™‚๏ธ 666 | 667 | Inversion of control means losing control over the code when using callbacks. 668 | 669 | - Control is given to another nested callback function, increasing dependency. 670 | - Essentially, we don't know what's happening behind the scenes. 671 | 672 | ### SOLUTION?? 673 | 674 | **Promises** ๐Ÿ”ฅ 675 | 676 | 677 | ![image](https://github.com/Tapesh-1308/linkedin-js-series/assets/71540051/c8c2aaea-ebb8-42be-bbfb-0d73735cf888) 678 | 679 | 680 | # JavaScript: Promises ๐Ÿ”ฅ 681 | 682 | A Promise is an assurance or guarantee that something will happen in the future. 683 | 684 | It can have two outcomes: 685 | - Fulfillment 686 | - Failure 687 | 688 | In JavaScript, 689 | a Promise is an object that will produce a single value after some time in the future. 690 | 691 | **Value:** 692 | - If successful: resolved value 693 | - If failed: reason 694 | 695 | Promises can have 3 possible states: 696 | - Pending: default state 697 | - Fulfilled: if successful 698 | - Rejected: if failed 699 | 700 | Promise transitions from: 701 | - pending -> fulfilled OR 702 | - pending -> rejected 703 | 704 | When using Promises, we have full control over the logic, allowing us to solve the inversion of control problem using promises. 705 | 706 | ### How to create promises? 707 | 708 | - Using `.then()` method: 709 | - It takes two callbacks: 710 | 1. If resolved 711 | 2. If rejected 712 | - `.then((value) => {}, (reason) => {})` 713 | 714 | - Always returns another promise, facilitating easy chaining. 715 | - Chaining helps solve the callback hell problem. 716 | 717 | ### How to handle errors in promises? 718 | 719 | - Using `.catch()` method: 720 | - If anything goes wrong in the promise, this method catches the reason for the error. 721 | - Using catch, errors no longer remain uncaught. 722 | 723 | ### `.finally()` 724 | 725 | - Method that always runs, regardless of whether resolved or rejected. 726 | - Here we can handle the result of promises whether rejected or resolved. 727 | 728 | 729 | ![image](https://github.com/Tapesh-1308/linkedin-js-series/assets/71540051/fd4aa8b8-bd57-4505-82ab-9e2991365311) 730 | 731 | 732 | # JavaScript: Promise APIs ๐Ÿ”ฅ๐Ÿ”ฅ 733 | 734 | Promises in JavaScript are used to handle asynchronous operations. There are several Promise APIs that allow you to work with multiple promises efficiently. 735 | 736 | ## Promise APIs 737 | 738 | ### 1. `Promise.all()` 739 | 740 | - Used to run multiple promises in parallel. 741 | - Takes an iterable (array) of promises as an argument. 742 | - If all promises are fulfilled, returns an array of values after resolving. 743 | - If any promise is rejected, stops running and returns the error immediately. 744 | - Implements fail-fast behavior. 745 | 746 | ### 2. `Promise.allSettled()` 747 | 748 | - Introduced after ES2020. 749 | - Returns an array of all settled promises, whether fulfilled or failed. 750 | - Each array value is an object with properties: 751 | - `status`: Indicates whether the promise was fulfilled or rejected. 752 | - `value` or `reason`: Contains the resolved value or rejection reason, respectively. 753 | 754 | ### 3. `Promise.race()` 755 | 756 | - Returns a single promise as output. 757 | - Returns the promise that settles first (either fulfilled or rejected). 758 | - If the fastest promise is resolved, it stops there, and other promises are not executed. 759 | - If the fastest promise is rejected, it will not get any error if other promises failed or not because they will not get executed. 760 | 761 | ### 4. `Promise.any()` 762 | 763 | - Returns a single promise that resolves when any of the provided promises resolves. 764 | - If no promise is fulfilled, returns an *aggregate error*. 765 | - *Aggregate Error*: Represents several errors wrapped in a single error. It provides the reasons for rejection of all promises in an array. 766 | 767 | ## Conclusion 768 | 769 | These Promise APIs provide powerful tools for handling asynchronous operations and managing multiple promises effectively. 770 | 771 | Next Topic: Async/Await ๐Ÿ”ฅ 772 | 773 | 774 | ![image](https://github.com/Tapesh-1308/linkedin-js-series/assets/71540051/d0cce268-c4fb-429c-bb5d-799fcaae3237) 775 | 776 | 777 | # JavaScript: Async/Await ๐Ÿ”ฅ 778 | 779 | Async/Await is syntactical sugar over `.then()` and `.catch()` chains, making promises handling more elegant. 780 | 781 | ## Async 782 | 783 | - Keyword to create an asynchronous function. 784 | - This function always returns a promise. If we don't explicitly return a promise, JavaScript automatically wraps the returned value in a promise. 785 | 786 | ## Await 787 | 788 | - Keyword that makes JavaScript wait until the promise is resolved or rejected. 789 | - Whenever the JavaScript engine encounters the `await` keyword, it suspends the complete function call from the call stack and continues with other work. 790 | - Once the promise is settled, the function comes back in the call stack and continues executing. 791 | 792 | `As time, tide, and JavaScript wait for none ๐Ÿ˜‰` 793 | 794 | ### Why Async/Await? 795 | 796 | - No need for nested callbacks. 797 | - Simplified syntax. 798 | - No chaining required. 799 | 800 | ## Error Handling 801 | 802 | - Use `try/catch` for error handling with Async/Await. 803 | 804 | ```javascript 805 | try { 806 | // Try to resolve promise here 807 | } catch (error) { 808 | // Do work when an error occurs 809 | } finally { 810 | // Run regardless of whether the promise is resolved or rejected 811 | } 812 | ``` 813 | 814 | ![image](https://github.com/Tapesh-1308/linkedin-js-series/assets/71540051/751d13e7-d63e-4750-9840-99fb397e0061) 815 | 816 | 817 | # JavaScript: `this` keyword ๐Ÿ”ฅ 818 | 819 | - `this` always refers to an object. 820 | - The object it refers to will vary depending on how and where `this` is being called. 821 | - It's not a variable, but a keyword (its value is not changed or reassigned). 822 | 823 | ## `this` in Global Scope 824 | 825 | - Refers to the global object: 826 | - `window` in the browser 827 | - `global` in Node.js 828 | 829 | ## `this` inside Functions 830 | 831 | - The value depends on strict/non-strict mode (will discuss in the next post): 832 | - In strict mode: `this` refers to `undefined`. 833 | - In non-strict mode: `this` refers to the global object. Why? 834 | - It also depends on how it is being called: 835 | - `function () {}`: `this` is `undefined`. 836 | - `window.function() {}`: `this` is `window` because it got a reference to the window. 837 | 838 | - This substitution: 839 | - If `this` is `undefined` or `null`, the `this` keyword will be replaced with the global object in non-strict mode. 840 | 841 | ## `this` inside an Object Method 842 | 843 | - Refers to the object. 844 | 845 | ## `this` inside Arrow Functions 846 | 847 | - Arrow functions do not have their own `this`. 848 | - They take `this` from their enclosing lexical environment. 849 | 850 | ## `this` inside DOM 851 | 852 | - Refers to the element where called: 853 | ```html 854 | 855 | ``` 856 | - Prints the button element. 857 | 858 | ## `this` in call(), apply(), bind() 859 | - Will see later. 860 | 861 | 862 | ![image](https://github.com/Tapesh-1308/linkedin-js-series/assets/71540051/7affd0a0-0adf-4e4a-98c3-58253c70bbb3) 863 | 864 | 865 | # JavaScript: "use strict" ๐Ÿ”ฅ 866 | 867 | "use strict" was introduced in ES5 and it makes JavaScript code execute in strict mode. It can be declared at the beginning of a script or a function. 868 | 869 | ## WHY? 870 | 871 | - **Easier to Write Secure JavaScript**: It helps catch common coding errors and unsafe actions, making code more robust. 872 | - **Throws Errors for Bad Syntax**: It throws errors for practices that are not considered good or safe. 873 | 874 | ## WHAT WE CAN'T DO? 875 | 876 | - Using variables/objects without declaring them using `var`, `let`, or `const`. 877 | - Deleting variables and function names. 878 | - Having duplicate parameters in a function. 879 | - Using octal numeric literals. 880 | - Writing to read-only properties. 881 | - Deleting undeletable properties. 882 | - Using certain keywords (`eval`, `arguments`, `private`, `public`, `static`, etc.) as variable names. 883 | - Declaring variables using the `eval` function. 884 | - This behaves differently inside functions. 885 | 886 | # JavaScript: call(), apply(), bind() ๐Ÿ”ฅ 887 | 888 | ## call() 889 | 890 | - **Purpose**: Change the context of the invoking function, allowing the replacement of the value of 'this' inside a function with any desired value. 891 | - **Syntax**: `func.call(newThisObj, arg1, arg2, ...)` 892 | - `newThisObj`: Value to replace 'this' inside the function. If not provided, the global object is considered. 893 | - `args`: Other required arguments for the function, if any. 894 | 895 | ## apply() 896 | 897 | - **Purpose**: Similar to `call()`, but arguments are passed as an array. 898 | - **Syntax**: `func.apply(newThisObj, [arg1, arg2, ...])` 899 | 900 | ## bind() 901 | 902 | - **Purpose**: Creates a copy of a function with a new value of 'this', which can be invoked later. 903 | - **Syntax**: `newFunc = func.bind(newThisObj, arg1, arg2, ...)` 904 | - `newFunc`: New function with the specified 'this' context. 905 | - `newThisObj`: Value to replace 'this' inside the function. 906 | - `args`: Other required arguments for the function. 907 | 908 | 909 | ![image](https://github.com/Tapesh-1308/linkedin-js-series/assets/71540051/61904420-1b35-436b-90c5-2ccf35d87758) 910 | 911 | 912 | # JavaScript: Currying ๐Ÿ› ๐Ÿ”ฅ 913 | 914 | Transforms a function with multiple arguments into a nested series of functions, each taking a single argument. 915 | 916 | f(a, b, c) -> f(a)(b)(c) โ˜ ๏ธ 917 | 918 | ## Why Currying? 919 | 920 | - helps avoid passing the same variable again and again 921 | - helps to create Higher Order Functions 922 | - fewer errors and side effects 923 | 924 | [enables checking method: checks if you have all the required things before you proceed] 925 | 926 | See the examples in the below image ๐Ÿ–ผ 927 | 928 | ## Currying vs Partial Application ๐Ÿ”ฅ 929 | 930 | - In currying, nested functions are equal to arguments, means each function must have a single argument. 931 | 932 | f(a, b, c) -> f(a)(b)(c) 933 | 934 | - Partial Application transforms a function into another function with smaller arguments (less args). 935 | 936 | f(a, b, c) -> f(a)(b, c) 937 | 938 | ## Currying using bind() 939 | 940 | - For currying, we can also use the bind function and separate the args in separate functions 941 | - because bind returns a new function. 942 | 943 | ```javascript 944 | curry = func.bind(this, arg1); 945 | curry(arg2); 946 | ``` 947 | โ˜ ๏ธ This topic needs a video reference to understand properly, so do YouTube โ–ถ๏ธ to see more examples. 948 | 949 | 950 | ![image](https://github.com/Tapesh-1308/linkedin-js-series/assets/71540051/eaa908d4-d703-422d-8e4f-9945b76cd359) 951 | 952 | 953 | # JavaScript: Prototype ๐Ÿ”ฅ๐Ÿ”ฅ 954 | 955 | In JS, objects can inherit properties from another object. 956 | 957 | The object from where these properties are inherited is called Prototype. 958 | 959 | Example: 960 | 961 | All methods that are built-in within strings, arrays, and objects data structure. 962 | 963 | --- 964 | 965 | ## Prototype Chain โ›“๏ธ 966 | 967 | If we are accessing any property from a string/array/function, the property is not only searched in itself but also in the prototype. This chain continues until it reaches null. 968 | 969 | ### Visualization ๐Ÿ” 970 | 971 | string --prototype-> object --prototype-> null 972 | 973 | array --prototype-> object --prototype-> null 974 | 975 | function --prototype-> object --prototype-> null 976 | 977 | ๐Ÿ‘€ Every object in JavaScript has an internal private property [[๐ฉ๐ซ๐จ๐ญ๐จ๐ญ๐ฒ๐ฉ๐ž]] 978 | 979 | - not accessible directly in code 980 | 981 | But to find [[๐ฉ๐ซ๐จ๐ญ๐จ๐ญ๐ฒ๐ฉ๐ž]] we can use ๐Ÿ‘‡๐Ÿป 982 | 983 | ```javascript 984 | Object.getPrototypeOf(arr); 985 | // or 986 | arr.__proto__ 987 | ``` 988 | 989 | 990 | ![image](https://github.com/Tapesh-1308/linkedin-js-series/assets/71540051/74e74b5a-bf7b-4251-9a54-b562eec3ee4c) 991 | 992 | 993 | ## Prototype Inheritance ๐Ÿ”ฅ 994 | 995 | The ability of JS objects to inherit properties from another object. 996 | 997 | Example: Array can access to all the properties of an object. 998 | Sure, here's the text converted directly into Markdown code: 999 | 1000 | # JavaScript: OOP Introduction๐Ÿ”ฅ 1001 | 1002 | JS is prototype based procedural language which means both functional and object oriented programming. 1003 | 1004 | ## โœŒ Two ways to achieve OOP in JS 1005 | 1006 | - Constructor Function 1007 | - Class keyword (ES6, syntactic sugar over constructor function) 1008 | 1009 | See the image below to compare syntaxes ๐Ÿ–ผ 1010 | 1011 | We can create multiple instances of the same class using the `new` keyword. 1012 | 1013 | ```javascript 1014 | const obj = new SomeClass(); 1015 | ``` 1016 | 1017 | ## ๐—ฃ๐—ฟ๐—ผ๐—ฏ๐—น๐—ฒ๐—บ ๐˜„๐—ถ๐˜๐—ต ๐—–๐—ผ๐—ป๐˜€๐˜๐—ฟ๐˜‚๐—ฐ๐˜๐—ผ๐—ฟ ๐—ณ๐˜‚๐—ป๐—ฐ๐˜๐—ถ๐—ผ๐—ป 1018 | 1019 | - Some common methods declared in the constructor function get duplicated in every instance, which is not memory efficient. 1020 | 1021 | So we need to put this common method in the prototype of the constructor function. 1022 | 1023 | Initially, `SomeClass.prototype` is an empty object. 1024 | 1025 | ```javascript 1026 | SomeClass.prototype.commonMethod = function () {} 1027 | ``` 1028 | 1029 | ๐Ÿ“ Here we can't use arrow function, because we need `this` referring to the class to access other class variables and methods. 1030 | 1031 | In class keyword syntax, methods are automatically put inside the prototype. 1032 | 1033 | 1034 | ![image](https://github.com/Tapesh-1308/linkedin-js-series/assets/71540051/a5065c6e-4037-4363-b41b-0b6f2b8eade7) 1035 | 1036 | ![image](https://github.com/Tapesh-1308/linkedin-js-series/assets/71540051/2f6cd48b-6e5b-43c6-8735-96bde307d936) 1037 | 1038 | 1039 | # JavaScript: Inheritance ๐Ÿ”ฅ๐Ÿ‘จโ€๐Ÿ‘ฆ 1040 | 1041 | We can inherit properties and methods of a parent class in a child class. 1042 | 1043 | ## To inherit 1044 | 1045 | ### In Constructor Function 1046 | 1047 | - To get properties: call the Parent constructor function with Child `this`. 1048 | - To get methods: link the prototypes. 1049 | 1050 | **Syntax:** 1051 | 1052 | ```javascript 1053 | function Child(name) { 1054 | Parent.call(this, name); // Pass the required args 1055 | } 1056 | Child.prototype = Object.create(Parent.prototype); 1057 | ``` 1058 | 1059 | - Make sure to write it above all child prototypes. 1060 | 1061 | ### Using Class Syntax 1062 | 1063 | - Use `extends` keyword. 1064 | - `super` keyword used to call the constructor of Parent. 1065 | 1066 | ```javascript 1067 | class Child extends Parent { 1068 | constructor(name) { 1069 | super(name); // Pass all the required args 1070 | } 1071 | } 1072 | ``` 1073 | 1074 | # JavaScript: Abstraction and Encapsulation ๐Ÿ”ฅ 1075 | 1076 | ## Abstraction 1077 | 1078 | We can make properties and methods private so that no one outside the class can access these properties. 1079 | 1080 | Use `#` before property or method name to declare it as a private entity. 1081 | 1082 | ## Encapsulation 1083 | 1084 | The process of hiding and securing properties of objects. We need to provide another mechanism to access these private properties. 1085 | 1086 | Using Getters and Setters, since we can access private properties within the class. 1087 | 1088 | Look at the image below showcasing two different syntaxes ๐Ÿ–ผ 1089 | 1090 | 1091 | ![image](https://github.com/Tapesh-1308/linkedin-js-series/assets/71540051/3343abe6-08cf-4181-a339-1f21ee62d0d4) 1092 | 1093 | ![image](https://github.com/Tapesh-1308/linkedin-js-series/assets/71540051/df18aef6-4783-4cb3-8e85-f79de2cd396c) 1094 | 1095 | 1096 | 1097 | # JavaScript: Static Properties and Methods ๐Ÿ”ฅ 1098 | 1099 | These are shared by all instances of a class. 1100 | 1101 | ```javascript 1102 | class MyClass { 1103 | static count = 0; 1104 | 1105 | static getCount() { 1106 | return MyClass.count; 1107 | } 1108 | } 1109 | ``` 1110 | 1111 | **Note:** 1112 | 1113 | - Can access static properties using class name or `this.constructor`. 1114 | - Cannot access from class instances. 1115 | - Static properties and methods are inherited. 1116 | - Static properties are initialized only once. 1117 | 1118 | ```javascript 1119 | const obj = new MyClass(); 1120 | console.log(obj.count); // undefined 1121 | 1122 | console.log(MyClass.count); // 0 1123 | ``` 1124 | 1125 | ## Static Block 1126 | 1127 | - We can create a static block which will run the first time a static method is used. 1128 | 1129 | ```javascript 1130 | static { 1131 | // ... 1132 | } 1133 | ``` 1134 | 1135 | ![image](https://github.com/Tapesh-1308/linkedin-js-series/assets/71540051/abee6354-8c93-493a-86cc-b12d00c07c1a) 1136 | 1137 | 1138 | # JavaScript: Event Bubbling & Capturing ๐Ÿ”ฅ 1139 | 1140 | Propagation refers to how an event travels through the DOM. 1141 | 1142 | ## โœŒ Phases of Propagation 1143 | 1144 | - **Bubbling** 1145 | - **Capturing** 1146 | 1147 | For simplicity, we are using the click event to understand. 1148 | 1149 | ### Bubbling ๐ŸŽฏ -> ๐ŸŒฑ 1150 | 1151 | - Propagation of an event from the target (clicked element) to the root (highest level parent of the target). 1152 | 1153 | If the target is a child: 1154 | 1. First, the child is clicked. 1155 | 2. Second, the parent is clicked. 1156 | 3. Third, the grandparent is clicked. 1157 | - And so on, until the root element where the last event occurs. 1158 | 1159 | ### Capturing (Trickling) ๐ŸŒฑ -> ๐ŸŽฏ 1160 | 1161 | - Propagation of an event from the root to the target. 1162 | 1163 | If the target is a child: 1164 | 1. First, the grandparent is clicked. 1165 | 2. Second, the parent is clicked. 1166 | 3. Third, the child is clicked. 1167 | 1168 | We can trigger bubbling/capturing and control over the propagation. 1169 | 1170 | ```javascript 1171 | ele.addEventListener(event, callback, useCapture); 1172 | ``` 1173 | 1174 | - **useCapture**: optional boolean value. 1175 | - Default: `false` (bubbling) 1176 | - `true` (capturing) 1177 | 1178 | ## Problem: 1179 | These propagations take time and increase workload. 1180 | 1181 | ### Solution? 1182 | 1183 | ```javascript 1184 | e.stopPropagation(); 1185 | ``` 1186 | 1187 | - Prevents further propagation. 1188 | - Stops all the parent event listeners but not other handlers on the target ๐ŸŽฏ. 1189 | 1190 | ```javascript 1191 | e.stopImmediatePropagation(); 1192 | ``` 1193 | 1194 | - Stops all the parent event listeners and other event listeners on the target as well. 1195 | 1196 | ![image](https://github.com/Tapesh-1308/linkedin-js-series/assets/71540051/619c21cc-b75e-4f1a-b04f-29bb3568034c) 1197 | 1198 | 1199 | # JavaScript: Event Delegation ๐Ÿ”ฅ 1200 | 1201 | Event delegation is a technique in JavaScript where we delegate the responsibility of handling an event to a parent element. 1202 | 1203 | By doing so: 1204 | 1205 | - โ˜‘๏ธ We avoid attaching multiple event listeners to individual child elements. 1206 | - โ˜‘๏ธ Performance improvement. 1207 | - โ˜‘๏ธ Dynamic (adding new elements will automatically have event listeners). 1208 | - โ˜‘๏ธ Code simplification. 1209 | 1210 | 1211 | ![image](https://github.com/Tapesh-1308/linkedin-js-series/assets/71540051/b222b897-fd5e-4efd-a9fa-fc73b0f5fc42) 1212 | 1213 | 1214 | # JavaScript: Script Loading ๐Ÿ”ฅ 1215 | 1216 | Three ways to load scripts: 1217 | 1218 | 1. `