[Go to site: main page, start]

0% found this document useful (0 votes)
12 views70 pages

JavaScript Fundamentals for Developers

Uploaded by

devansh.shr
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
12 views70 pages

JavaScript Fundamentals for Developers

Uploaded by

devansh.shr
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

A Full-Stack Developer's Deep Dive into

Modern JavaScript

Section 1: The Bedrock of JavaScript - Core


Fundamentals

This section establishes the non-negotiable foundation of the language. Mastery here is not
just about knowing syntax but understanding the underlying mechanics that govern how
JavaScript code behaves. The focus is on the "why" behind the rules, connecting them to
code predictability, bug prevention, and professional best practices essential for building
large-scale, maintainable applications.

1.1 Variables, Scope, and Hoisting: From Ambiguity to Predictability

The evolution of variable declaration in JavaScript, from the historical var to the modern
standards of let and const, reflects the language's maturation toward a more predictable and
robust model suitable for complex applications.1

var: The Function-Scoped Legacy

Variables declared with var are function-scoped. This means they are accessible anywhere
within the function they are declared in, regardless of block boundaries ({...}). They are also
"hoisted" to the top of their scope and initialized with a value of undefined.2 This behavior can
lead to subtle bugs that are difficult to trace, particularly in loops and conditional statements.

Implementation: The var Hoisting Problem


The following code demonstrates how var is hoisted. The variable x is accessible before its
declaration, but its value is undefined until the assignment is reached.

JavaScript

[Link](x); // Outputs: undefined (Hoisted, but not yet assigned)


var x = 5;
[Link](x); // Outputs: 5

if (true) {
var y = 10;
}
[Link](y); // Outputs: 10 (var is not block-scoped)

A classic problem occurs when using var in loops with asynchronous callbacks, such as
setTimeout.

JavaScript

for (var i = 0; i < 3; i++) {


setTimeout(function() {
[Link](i); // What will this log?
}, 100);
}
// Outputs: 3, 3, 3

Because var i is function-scoped, all three setTimeout callbacks share the same i variable. By
the time the callbacks execute (after the loop has finished), the value of i is 3.

let and const: Block Scope and the Temporal Dead Zone

ES6 introduced let and const to address the shortcomings of var. Both are block-scoped,
meaning they are only accessible within the block ({...}) in which they are declared.2

This change forces developers to write more disciplined, predictable code, directly
addressing the maintenance and reliability challenges of large-scale systems. The
introduction of block scope was a direct solution to the real-world engineering problem of
unintended variable leakage and mutation.1

Furthermore, let and const are hoisted but are not initialized. The period between entering
their scope and their declaration is called the Temporal Dead Zone (TDZ). Accessing a
variable in the TDZ results in a ReferenceError, which prevents bugs caused by using a
variable before it is declared.2

Implementation: let in Loops

Revisiting the previous loop example with let solves the problem. A new i is created for each
loop iteration, and the closure for each setTimeout captures a different instance of i.

JavaScript

for (let i = 0; i < 3; i++) {


setTimeout(function() {
[Link](i);
}, 100);
}
// Outputs: 0, 1, 2

Implementation: The Temporal Dead Zone (TDZ)

JavaScript

// [Link](a); // ReferenceError: Cannot access 'a' before initialization


let a = 10;

{
// [Link](b); // ReferenceError: Cannot access 'b' before initialization
const b = 20;
}

const: Immutable Assignment

The const declaration is also block-scoped but creates a read-only reference to a value. This
does not mean the value itself is immutable, but that the variable identifier cannot be
reassigned.1

Implementation: const with Objects

While you cannot reassign a const variable, you can mutate the properties of an object it
references. This is a crucial distinction.

JavaScript

const person = {
name: 'Alice',
age: 30
};

// This is allowed: Mutating the object's property


[Link] = 31;
[Link]([Link]); // Outputs: 31

// This will throw an error: Reassigning the constant


// person = { name: 'Bob', age: 40 }; // TypeError: Assignment to constant variable.

Variable Declaration Comparison

Feature var let const


Scope Function Block Block

Hoisting Behavior Hoisted and Hoisted but not Hoisted but not
initialized to initialized (TDZ) initialized (TDZ)
undefined

Re-assignable? Yes Yes No

Re-declarable? Yes No No

Temporal Dead No Yes Yes


Zone

Real-World Coding Challenges

1. Refactor a Loop: Take a piece of code that uses var in a for loop with an asynchronous
callback (like setTimeout or a fetch request) and refactor it to use let to produce the
correct, sequential output.
2. Scope Debugging: Create a nested function structure with variables declared using var,
let, and const at different levels (global, outer function, inner function, block). Write a
function that attempts to access these variables from various scopes and predict which
ones will be accessible and which will throw errors.
3. Constant Configuration Object: Design a configuration module for an application. Use
a const object to hold settings like API keys, base URLs, and feature flags. Write
functions that read from this object. Then, demonstrate why attempting to reassign the
entire configuration object fails, while updating a nested property (if it's not frozen)
would succeed.
4. The TDZ Puzzle: Write a function where a let-declared variable is shadowed inside a
block. Place [Link] statements both inside and outside the block, including one
within the TDZ, to demonstrate how the TDZ works and how variable shadowing behaves
with block scope.
1.2 Data Types and Structures: Memory and Mutability

JavaScript's data types are categorized into two main groups: primitive types and the
object type. This distinction is fundamental because it dictates how values are stored in
memory, how they are passed to functions, and how they are compared.3

Primitive Types

There are seven primitive data types. They are immutable, meaning their values cannot be
changed once created. They are stored directly in memory, typically on the stack, which is a
highly efficient memory location for static data.3

● String: Represents textual data. Can be created with single quotes, double quotes, or
backticks (template literals).3
● Number: Represents both integer and floating-point numbers. Includes special values
like Infinity, -Infinity, and NaN (Not-a-Number).3
● BigInt: Represents integers of arbitrary length, useful for numbers beyond the safe
integer limit of the Number type.3
● Boolean: Represents logical values true and false.3
● undefined: Represents a variable that has been declared but not assigned a value.3
● null: Represents the intentional absence of any object value.3
● Symbol: Represents a unique and immutable identifier, often used as keys for object
properties to avoid naming collisions.3

Implementation: Primitive Types in Action

JavaScript

// String
let greeting = 'Hello';
let name = "World";
let message = `${greeting}, ${name}!`; // Template literal
[Link](message); // "Hello, World!"
// Number
let integer = 100;
let float = 99.5;
let notANumber = "abc" / 2;
[Link](notANumber); // NaN

// BigInt
const largeNumber = 9007199254740991n;
const anotherLargeNumber = largeNumber + 1n;
[Link](anotherLargeNumber); // 9007199254740992n

// Boolean
let isLoggedIn = true;
let hasPermission = false;

// undefined
let user;
[Link](user); // undefined

// null
let selectedProduct = null;

// Symbol
const id1 = Symbol('id');
const id2 = Symbol('id');
[Link](id1 === id2); // false

The Object Type (Reference Types)

The object type is the only non-primitive type. This includes object literals, arrays, and
functions. Unlike primitives, objects are stored on the heap, a larger, more dynamic memory
space. A variable holding an object does not store the object itself, but rather a reference (a
memory address) to where the object is located on the heap.4

This pass-by-reference behavior is a critical concept. When an object is passed to a function,


a copy of the reference is passed, not a copy of the object. Therefore, if the function
modifies the object via that reference, the original object is mutated. This can lead to
unintended side effects if not managed carefully, which is a core challenge in state
management for large applications.4
Implementation: Primitives vs. Objects (Pass-by-Value vs. Pass-by-Reference)

JavaScript

// Pass-by-Value (Primitives)
let a = 10;
let b = a; // 'b' gets a copy of the value of 'a'
b = 20; // Changing 'b' does not affect 'a'

[Link](a); // 10
[Link](b); // 20

// Pass-by-Reference (Objects)
let user1 = { name: 'Alice' };
let user2 = user1; // 'user2' gets a copy of the reference to the same object

[Link] = 'Bob'; // Mutating the object via the reference in 'user2'

[Link]([Link]); // 'Bob' (The original object was changed)


[Link]([Link]); // 'Bob'

Real-World Application: State Management

In a React application, state is often held in objects. If a component passes its state object to
a child component, and that child component directly mutates a property of the object, it
causes an unintended side effect that breaks React's one-way data flow. This is why state
updates must be immutable—creating a new object with the updated properties rather than
modifying the original. Understanding the pass-by-reference nature of objects is the
foundation for understanding immutable state management patterns.

The typeof Operator

The typeof operator returns a string indicating the type of an operand. It is useful for basic
type checking, but has some well-known quirks.3

Implementation: typeof Examples


JavaScript

[Link](typeof "hello"); // "string"


[Link](typeof 123); // "number"
[Link](typeof true); // "boolean"
[Link](typeof 123n); // "bigint"
[Link](typeof Symbol('id')); // "symbol"
[Link](typeof undefined); // "undefined"

// Quirks
[Link](typeof { a: 1 }); // "object"
[Link](typeof); // "object" (Arrays are objects)
[Link](typeof null); // "object" (A historical bug in JavaScript)
[Link](typeof function(){}); // "function" (Technically a callable object)

To reliably check if a value is an array, use [Link]().4

Real-World Coding Challenges

1. Data Type Classifier: Write a function that takes one argument and returns a string
identifying its specific data type. It should correctly identify "string", "number", "bigint",
"boolean", "undefined", "symbol", "null", "array", "object", and "function".
2. Immutable Update Function: Create a function updateUser that takes a user object
and an updates object. It should return a new user object with the updates applied,
without modifying the original user object. This demonstrates the principle of
immutability.
3. Shopping Cart State: Simulate a shopping cart using an array of objects. Write
functions to add an item, remove an item, and update an item's quantity. Ensure that
each function returns a new cart array rather than mutating the original, mimicking state
management best practices.
4. Reference vs. Value Puzzle: Create a function that accepts two arguments, one
primitive and one object. Inside the function, modify both arguments. Outside the
function, log the values of the original variables to demonstrate which one was affected
by the function call and explain why.
1.3 Operators and Type Coercion: The Case for Strictness

JavaScript operators are symbols that perform operations on values and variables. A key
feature of the language is its automatic type coercion, where it implicitly converts values
from one type to another during operations. While this can be convenient, it is also a common
source of bugs.9

Operator Categories

● Arithmetic Operators: Perform mathematical calculations (+, -, *, /, % remainder, **


exponentiation).10
● Assignment Operators: Assign values to variables (=, +=, -=).10
● Comparison Operators: Compare two values and return a boolean. This category
includes both strict (===, !==) and loose (==, !=) operators.9
● Logical Operators: Combine or invert boolean values (&& AND, || OR, ! NOT). They also
perform "short-circuiting".10
● Ternary Operator: A concise conditional operator (condition? valueIfTrue :
valueIfFalse).11

Implementation: Operator Examples

JavaScript

// Arithmetic
let sum = 10 + 5; // 15
let power = 2 ** 3; // 8

// Assignment
let score = 100;
score += 10; // score is now 110

// Logical (Short-circuiting)
let user = null;
let username = user && [Link]; // Stops at user, username is null
let defaultName = user |

| 'Guest'; // user is falsy, defaultName is 'Guest'

Type Coercion and the Case for Strict Equality

JavaScript's loose equality operator (==) performs type coercion before comparing values.
This can lead to non-intuitive results.

Implementation: Loose (==) vs. Strict (===) Equality

JavaScript

[Link](10 == '10'); // true (string '10' is coerced to number 10)


[Link](0 == false); // true (boolean false is coerced to number 0)
[Link](null == undefined); // true (a special case in the language spec)

[Link](10 === '10'); // false (different types)


[Link](0 === false); // false (different types)
[Link](null === undefined); // false (different types)

In professional development, relying on the complex rules of implicit coercion is considered a


significant risk. It can mask underlying data type inconsistencies that lead to subtle, hard-to-
diagnose bugs. For this reason, the industry-standard best practice, enforced by tools like
ESLint, is to exclusively use the strict equality (===) and strict inequality (!==)
operators. This forces developers to be explicit about type conversions (e.g., using
Number(value) or String(value)), resulting in code that is more predictable, readable, and
robust.10

Real-World Coding Challenges

1. Falsy Value Filter: Write a function that takes an array containing a mix of values (e.g.,
0, "", null, undefined, NaN, false, {}, ``, "hello") and returns a new array containing only
the "truthy" values.
2. Strict Equality Validator: Create a function isSameTypeAndValue that takes two
arguments and returns true only if they are strictly equal (===), otherwise false. Use this
function to test various pairs like 0 and false, "" and false, null and undefined.
3. Short-Circuiting for Default Values: Write a function that configures a user profile. It
should accept an options object that may be missing some properties. Use the logical
OR (||) operator to assign default values for username, theme, and isAdmin if they are
not provided.
4. Coercion Debugger: You are given a buggy function buggySum(a, b) that is supposed
to add two numbers but sometimes concatenates them as strings. Identify why
buggySum('5', 5) returns "55" and fix it by explicitly coercing the inputs to numbers
before the addition.

1.4 Control Flow and Iteration: Tools for Algorithmic Thinking

Control flow statements dictate the order in which code is executed, allowing for decision-
making and repetition. Mastery of these structures is essential for implementing any kind of
logic or algorithm.13

Conditional Statements

● if...else: The fundamental conditional statement for executing different code blocks
based on a condition.13
● switch: A useful alternative to a long if...else if chain when comparing a single value
against multiple possible cases.11

Implementation: User Role Authorization

This example uses if...else if...else to check a user's role and grant access accordingly. A
switch statement could also be used here effectively.

JavaScript
function checkAccess(userRole) {
if (userRole === 'admin') {
[Link]('Full access granted.');
} else if (userRole === 'editor') {
[Link]('Access granted to edit content.');
} else if (userRole === 'viewer') {
[Link]('View-only access granted.');
} else {
[Link]('Access denied.');
}
}

checkAccess('editor'); // "Access granted to edit content."

Looping and Iteration

● for loop: The classic loop, giving you control over the iterator, condition, and increment
step.
● while loop: Executes a block of code as long as a condition is true. Useful when the
number of iterations is not known beforehand.
● for...in loop: Iterates over the enumerable property keys of an object. It should not be
used to iterate over arrays, as it can include inherited properties and does not guarantee
order.16
● for...of loop: The modern, preferred method for iterating over the values of an iterable
object (like an Array, String, Map, or Set). It is more concise and less error-prone than a
traditional for loop for this purpose.17

Implementation: Iterating Over an Array

This example contrasts the modern for...of loop with the traditional for loop for iterating
through an array's values.

JavaScript

const fruits = ['apple', 'banana', 'cherry'];


// Modern approach: for...of (preferred for iterable values)
[Link]('--- Using for...of ---');
for (const fruit of fruits) {
[Link](fruit);
}

// Traditional approach: for loop


[Link]('--- Using traditional for loop ---');
for (let i = 0; i < [Link]; i++) {
[Link](fruits[i]);
}

The for...of loop is cleaner because it directly accesses the value without needing to manage
an index variable (i), which prevents common "off-by-one" errors.

Implementation: Iterating Over Object Properties

The for...in loop is used to inspect the keys of an object. It is best practice to include a check
with [Link]() to ensure you are only processing the object's own
properties, not inherited ones.16

JavaScript

const user = {
name: 'John Doe',
email: '[Link]@[Link]',
isAdmin: false
};

[Link]('--- User Properties ---');


for (const key in user) {
if ([Link](user, key)) {
[Link](`${key}: ${user[key]}`);
}
}

Real-World Coding Challenges


1. Grade Categorizer: Write a function that takes a numerical score (0-100) and returns a
letter grade ('A', 'B', 'C', 'D', 'F') using an if...else if...else structure.13
2. Day of the Week: Create a function that takes a number (1-7) and returns the
corresponding day of the week ('Sunday' for 1, 'Monday' for 2, etc.) using a switch
statement. Include a default case for invalid numbers.13
3. Sum of Even Numbers: Given an array of numbers, use a for...of loop and an if
condition to calculate the sum of only the even numbers in the array.
4. Object Property Lister: Write a function that takes an object and logs all of its own key-
value pairs to the console using a for...in loop with a hasOwnProperty check.

Section 2: Data Structures in Depth

Beyond primitive types, JavaScript provides a powerful set of built-in data structures for
organizing and manipulating collections of data. Understanding the strengths and use cases
of each is fundamental to writing efficient, scalable, and readable code.

2.1 The Object: The Universal Building Block

In JavaScript, the object is the most fundamental data structure. At its core, an object is a
dynamic collection of key-value pairs, where keys are strings (or Symbols) and values can be
any data type, including other objects, arrays, and functions.8

Implementation: Object Literals

The most common way to create an object is with the object literal syntax {}.

JavaScript

const userProfile = {
username: 'dev_user',
email: 'dev@[Link]',
isActive: true,
followers: 150,
followedTags: ['javascript', 'webdev', 'react'],
lastLogin: new Date('2023-10-27T10:00:00Z'),
notify() {
[Link](`Notifying ${[Link]} via ${[Link]}`);
}
};

// Accessing properties with dot notation


[Link]([Link]); // 'dev_user'

// Accessing properties with bracket notation (useful for dynamic keys)


const key = 'email';
[Link](userProfile[key]); // 'dev@[Link]'

// Calling a method
[Link](); // 'Notifying dev_user via dev@[Link]'

Real-World Application: Configuration Management

Objects are perfect for storing configuration settings for an application. This centralizes
settings, making them easy to manage and access throughout the codebase.

JavaScript

const appConfig = {
apiUrl: '[Link]
timeout: 5000,
features: {
enableBeta: true,
showAds: false
}
};

function getApiUrl() {
return [Link];
}

A Comprehensive Guide to Object Methods

JavaScript provides a rich set of static methods on the Object constructor to inspect,
manipulate, and manage objects.
● [Link](obj): Returns an array of an object's own enumerable property names
(keys).
● [Link](obj): Returns an array of an object's own enumerable property values.76
● [Link](obj): Returns a nested array of an object's own enumerable [key, value]
pairs.76
● [Link](target,...sources): Copies all enumerable own properties from one or
more source objects to a target object. It returns the modified target object.76
● [Link](proto, [propertiesObject]): Creates a new object with the specified
prototype object and optional properties.
● [Link](obj): Freezes an object, preventing new properties from being added and
existing properties from being modified or removed.78
● [Link](obj): Seals an object, preventing new properties from being added and
existing ones from being removed, but allows values of existing properties to be
changed.76
● [Link](obj, prop): A modern and safer way to check if an object has a
specified property as its own direct property (not inherited).76
● [Link](obj): Returns an array of all properties (enumerable or
not) found directly on a given object.76

Implementation: Using Object Methods

JavaScript

const product = {
id: 'abc-123',
name: 'Laptop',
price: 1200,
inStock: true
};

// Get all keys


const keys = [Link](product);
[Link](keys); //

// Get all values


const values = [Link](product);
[Link](values); // ['abc-123', 'Laptop', 1200, true]

// Get all key-value pairs


const entries = [Link](product);
[Link](entries); // [['id', 'abc-123'], ['name', 'Laptop'],...]

// Create a new object with additional properties


const productWithDetails = [Link]({}, product, { brand: 'TechCo', warranty: '2 years' });
[Link](productWithDetails); // { id: 'abc-123', name: 'Laptop',..., brand: 'TechCo',... }

// Check for own property


[Link]([Link](product, 'name')); // true
[Link]([Link](product, 'toString')); // false (inherited)

Real-World Coding Challenges

1. Object Property Counter: Write a function that takes an object and returns the number
of its own properties using [Link]().
2. Dynamic Property Updater: Create a function that takes an object, a property name
(as a string), and a new value. The function should update the object's property and
return the modified object.
3. Object Merger: Write a function that takes two objects and merges them into a new
object using [Link](). If there are conflicting keys, the second object's value
should take precedence.
4. Object to Query String: Create a function that converts an object into a URL query
string (e.g., { a: 1, b: 'hello' } becomes "a=1&b=hello") using [Link]() and array
methods.

2.2 The Array: Ordered Collections


An array is an ordered list of values. Each value is called an element, and it is identified by an
index. JavaScript arrays are zero-indexed, dynamic (their size can change), and can hold
elements of different data types.18

A Comprehensive Guide to Array Methods

Adding/Removing Elements (Mutating)

● .push(element1,..., elementN): Adds one or more elements to the end of an array and
returns the new length.
● .pop(): Removes the last element from an array and returns that element.
● .unshift(element1,..., elementN): Adds one or more elements to the beginning of an
array and returns the new length.
● .shift(): Removes the first element from an array and returns that removed element.

Implementation: push, pop, shift, unshift

JavaScript

let tasks =;

[Link]('Build a Project'); // tasks is now


[Link]([Link]); // 3

const removedTask = [Link](); // removedTask is 'Build a Project', tasks is back to its original
state
[Link](removedTask);

[Link]('Setup Environment'); // tasks is now


[Link](tasks); // 'Setup Environment'
const firstTask = [Link](); // firstTask is 'Setup Environment'
[Link](firstTask);

Creating New Arrays from Existing Ones (Non-Mutating)

● .slice(start, end): Returns a shallow copy of a portion of an array into a new array. The
original array is not modified.80
● .concat(array2,..., arrayN): Merges two or more arrays. This method does not change
the existing arrays but instead returns a new array.81

Implementation: slice and concat

JavaScript

const numbers = ;

const middleNumbers = [Link](2, 5); // Extracts elements from index 2 up to (but not
including) 5
[Link](middleNumbers); // [2, 3, 4]
[Link](numbers); // (original is unchanged)

const moreNumbers = [6, 7, 8];


const combined = [Link](moreNumbers);
[Link](combined); //

Modifying in Place (Mutating)

● .splice(start, deleteCount, item1,..., itemN): Changes the contents of an array by


removing or replacing existing elements and/or adding new ones in place.82
● .sort(compareFunction): Sorts the elements of an array in place. The default sort order
is lexicographical (string-based).81

Implementation: splice and sort


JavaScript

let months = ['Jan', 'March', 'April', 'June'];


[Link](1, 0, 'Feb'); // Inserts 'Feb' at index 1
[Link](months); // ['Jan', 'Feb', 'March', 'April', 'June']

[Link](4, 1, 'May'); // Replaces 1 element at index 4


[Link](months); // ['Jan', 'Feb', 'March', 'April', 'May']

const unsortedNumbers = [4, 2, 5, 1, 3];


[Link]((a, b) => a - b); // Sorts numerically
[Link](unsortedNumbers); // [1, 2, 3, 4, 5]

Iteration Methods

● .forEach(callback): Executes a provided function once for each array element. It does
not return a new array.83
● .map(callback): Creates a new array populated with the results of calling a provided
function on every element.19
● .filter(callback): Creates a new array with all elements that pass the test implemented
by the provided function.20
● .reduce(callback, initialValue): Executes a "reducer" function on each element,
resulting in a single output value.21

Implementation: Iteration Methods

JavaScript

const numbers = [1, 2, 3, 4, 5];

//.forEach(): Log each number


[Link](num => [Link](num * 2)); // Logs 2, 4, 6, 8, 10
//.map(): Create a new array of squared numbers
const squared = [Link](num => num * num);
[Link](squared); // [1, 4, 9, 16, 22]

//.filter(): Create a new array of only odd numbers


const odds = [Link](num => num % 2!== 0);
[Link](odds); // [1, 3, 5]

//.reduce(): Calculate the product of all numbers


const product = [Link]((acc, current) => acc * current, 1);
[Link](product); // 120

Searching and Finding

● .find(callback): Returns the first element that satisfies the provided testing function.
● .findIndex(callback): Returns the index of the first element that satisfies the testing
function.84
● .includes(valueToFind, fromIndex): Determines whether an array includes a certain
value, returning true or false.
● .some(callback): Tests whether at least one element in the array passes the test.
● .every(callback): Tests whether all elements in the array pass the test.

Implementation: Searching Methods

JavaScript

const users =;

//.find(): Find the user with id 2


const userBob = [Link](user => [Link] === 2);
[Link]([Link]); // 'Bob'

//.findIndex(): Find the index of the admin


const adminIndex = [Link](user => [Link] === 'admin');
[Link](adminIndex); // 0
//.some(): Check if there is at least one editor
const hasEditor = [Link](user => [Link] === 'editor');
[Link](hasEditor); // true

//.every(): Check if all users are admins


const allAdmins = [Link](user => [Link] === 'admin');
[Link](allAdmins); // false

Real-World Coding Challenges

1. Array to Object: Write a function that converts an array of user objects into a single
object where the keys are the user IDs.
2. Product Filter: Given an array of product objects, write a function that filters out
products that are out of stock and returns an array of the names of the available
products using .filter() and .map().
3. Total Cart Value: Using .reduce(), write a function that calculates the total price of all
items in a shopping cart array (where each item has price and quantity properties).
4. Remove and Insert: Given an array of numbers, use .splice() to remove the middle
element and insert two new numbers in its place.
5. Sort Users by Name: You have an array of user objects, each with a name property. Use
.sort() to sort the array alphabetically by user name.

2.3 Set: Collections of Unique Values

A Set is a collection of unique values. A value in a Set may only occur once; it is unique in the
Set's collection. Sets are particularly useful for tasks like removing duplicate elements from
an array or checking for the presence of an item in a collection where performance is
critical.18

Implementation: Set Basics

JavaScript
// Create a Set from an array with duplicates
const numbers = [1, 2, 3, 2, 4, 1, 5];
const uniqueNumbers = new Set(numbers);
[Link](uniqueNumbers); // Set(5) { 1, 2, 3, 4, 5 }

// Add a new element


[Link](6);
[Link](uniqueNumbers); // Set(6) { 1, 2, 3, 4, 5, 6 }

// Adding a duplicate element does nothing


[Link](1);
[Link](uniqueNumbers); // Set(6) { 1, 2, 3, 4, 5, 6 }

// Check for the presence of an element


[Link]([Link](3)); // true
[Link]([Link](10)); // false

// Delete an element
[Link](2);
[Link](uniqueNumbers); // Set(5) { 1, 3, 4, 5, 6 }

// Get the size


[Link]([Link]); // 5

// Iterate over a Set


for (const num of uniqueNumbers) {
[Link](num);
}

Real-World Application: Managing User Roles or Tags

Sets are excellent for managing a collection of unique items, such as the roles assigned to a
user or the tags on a blog post, where duplicates are not allowed.

JavaScript

class User {
constructor(name) {
[Link] = name;
[Link] = new Set();
}

addRole(role) {
[Link](role);
}

hasRole(role) {
return [Link](role);
}
}

const user = new User('Alice');


[Link]('editor');
[Link]('viewer');
[Link]('editor'); // This will be ignored

[Link]([Link]); // Set(2) { 'editor', 'viewer' }


[Link]([Link]('admin')); // false

Real-World Coding Challenges

1. Array Deduplication: Write a function that takes an array and returns a new array with
all duplicate values removed.
2. Set Intersection: Create a function that takes two Sets and returns a new Set
containing only the elements that are present in both Sets.
3. Unique Tag Collector: You are given an array of blog post objects, where each object
has a tags array. Write a function to collect all unique tags from all posts into a single
Set.
4. Check for Uniqueness: Write a function that takes an array and returns true if all its
elements are unique, and false otherwise, using a Set for an efficient implementation.

2.4 Map: Keyed Collections with Any Type


A Map is a collection of keyed data items, similar to an object. However, the main difference is
that Map allows keys of any type (including objects, functions, and other data types),
whereas object keys are implicitly converted to strings.23 Maps also maintain the insertion
order of their elements.

Implementation: Map Basics

JavaScript

const userMap = new Map();

const user1 = { id: 1, name: 'Alice' };


const user2 = { id: 2, name: 'Bob' };

// Set key-value pairs


[Link](user1, { role: 'admin', lastLogin: '2023-10-27' });
[Link](user2, { role: 'editor', lastLogin: '2023-10-26' });

// Get a value by key


[Link]([Link](user1)); // { role: 'admin',... }

// Check for the presence of a key


[Link]([Link](user2)); // true

// Get the size


[Link]([Link]); // 2

// Iterate over a Map


for (const [user, metadata] of userMap) {
[Link](`${[Link]}'s role is ${[Link]}`);
}

// Delete an entry
[Link](user1);
[Link]([Link]); // 1

Real-World Application: Storing Metadata for DOM Elements

A powerful use case for Maps is to associate metadata with objects without modifying the
objects themselves. For example, you can map DOM elements to related data, which is
cleaner than adding custom properties directly to the elements.

JavaScript

const elementMetadata = new Map();

const button1 = [Link]('#btn1');


const button2 = [Link]('#btn2');

[Link](button1, { clicks: 0, trackingId: 'header-promo' });


[Link](button2, { clicks: 0, trackingId: 'footer-signup' });

[Link]('click', () => {
const metadata = [Link](button1);
[Link]++;
[Link](`Button ${[Link]} clicked ${[Link]} times.`);
});

Real-World Coding Challenges

1. Frequency Counter: Write a function that takes an array of numbers and returns a Map
where the keys are the numbers and the values are their frequencies in the array.
2. Object to Map: Create a function that converts an object into a Map using
[Link]().
3. Anagram Grouping: Given an array of strings, group the anagrams together. The
function should return a Map where keys are sorted character strings and values are
arrays of the original anagram strings.
4. Cache Implementation: Implement a simple caching mechanism using a Map. Create a
function that takes a key and a "fetcher" function. If the key exists in the Map, return its
value; otherwise, call the fetcher function, store the result in the Map, and then return it.

Section 3: Functions - The Building Blocks of Logic


Functions are the core unit of organization, reusability, and abstraction in JavaScript. This
section explores not just how to write functions, but how they interact with their surrounding
state (scope and closures) and their execution context (this), concepts that are fundamental
to building any non-trivial application.

3.1 The Many Faces of Functions: Declarations, Expressions, and


Arrows

JavaScript provides three primary ways to define functions, each with distinct characteristics
regarding hoisting and context (this).25

● Function Declarations: Defined with the function keyword followed by a name. They are
fully hoisted, meaning the entire function definition is moved to the top of its scope,
allowing it to be called before it appears in the code.25
● Function Expressions: An anonymous or named function assigned to a variable. Only
the variable declaration is hoisted, not the function assignment itself. This means it
cannot be called before the line where it is defined.26
● Arrow Functions (ES6): Provide a more concise syntax and, crucially, do not have their
own this context. They lexically inherit this from their surrounding scope.25

Implementation: Comparing Function Types

JavaScript

// Function Declaration (Hoisted)


[Link](declaredFunction()); // "I am declared!"

function declaredFunction() {
return "I am declared!";
}

// Function Expression (Not hoisted)


// [Link](expressedFunction()); // TypeError: expressedFunction is not a function
const expressedFunction = function() {
return "I am expressed!";
};
[Link](expressedFunction()); // "I am expressed!"

// Arrow Function (Concise syntax)


const add = (a, b) => a + b;
[Link](add(5, 3)); // 8

The most significant difference introduced by arrow functions is their handling of this. Before
ES6, developers frequently encountered issues where this inside a callback function would
refer to the global object instead of the intended object method's context. This necessitated
workarounds like const self = this; or using .bind(). Arrow functions solve this problem by
design.

Implementation: Arrow Functions and Lexical this

JavaScript

const team = {
name: 'Developers',
members:,

// Pre-ES6 approach with a workaround


displayMembersOld: function() {
const self = this; // 'this' refers to the 'team' object
[Link](function(member) {
// 'this' inside this callback would be the global object without the 'self' workaround
[Link](`${member} is on team ${[Link]}`);
});
},

// Modern approach with Arrow Function


displayMembersNew: function() {
// 'this' refers to the 'team' object
[Link]((member) => {
// The arrow function inherits 'this' from the surrounding 'displayMembersNew' scope
[Link](`${member} is on team ${[Link]}`);
});
}
};

[Link]();
[Link]();

Real-World Coding Challenges

1. Hoisting Puzzle: Write a script that calls a function before it is declared. Implement this
first with a function declaration to show that it works, and then convert it to a function
expression to show that it fails. Explain the concept of hoisting in your comments.
2. Refactor to Arrow Functions: Take a block of code that uses traditional anonymous
functions for array methods (e.g., .map, .filter, .reduce) and refactor it to use the more
concise arrow function syntax.
3. this Context Bug Fix: You are given an object with a method that uses setTimeout with
a traditional function callback, which causes this to be lost. Fix the bug by converting the
callback to an arrow function.
4. Function Factory: Create a function expression named createMultiplier that takes a
number as an argument and returns an arrow function. The returned function should
take another number and return the product of the two numbers.

3.2 Closures and Lexical Environments: Remembering State

A closure is the combination of a function and the lexical environment within which that
function was declared. In practice, this means an inner function has access to the variables of
its outer (enclosing) function, even after the outer function has finished executing.27 This is
not an obscure feature but a fundamental mechanism that enables powerful patterns like
data encapsulation and function factories.

Implementation: A Basic Closure

The innerFunction "closes over" the outerVariable, maintaining access to it even when
myClosure is called later, long after outerFunction has returned.
JavaScript

function outerFunction() {
const outerVariable = 'I am from the outside!';

function innerFunction() {
[Link](outerVariable);
}

return innerFunction;
}

const myClosure = outerFunction();


myClosure(); // Outputs: "I am from the outside!"

Real-World Use Cases for Closures

1. Data Encapsulation and Private State (Module Pattern)

Closures are the classic way to create private state in JavaScript. By wrapping logic in an
Immediately Invoked Function Expression (IIFE), you can create variables that are
inaccessible from the outside world, exposing only a public interface.28

Implementation: A Private Counter

JavaScript

const counter = (function() {


let privateCount = 0; // This variable is private to the closure

function changeBy(val) {
privateCount += val;
}
return {
increment: function() {
changeBy(1);
},
decrement: function() {
changeBy(-1);
},
value: function() {
return privateCount;
}
};
})();

[Link]([Link]()); // 0
[Link]();
[Link]();
[Link]([Link]()); // 2
// [Link]([Link]); // undefined - cannot be accessed directly

2. Function Factories

A function factory is a function that creates and returns other functions. These returned
functions are pre-configured with data from the factory's scope, thanks to closures.27

Implementation: A Logging Factory

JavaScript

function createLogger(level) {
const colors = {
info: 'blue',
warn: 'orange',
error: 'red'
};

return function(message) {
[Link](`%c[${[Link]()}]: ${message}`, `color: ${colors[level]}`);
};
}

const infoLogger = createLogger('info');


const warnLogger = createLogger('warn');
const errorLogger = createLogger('error');

infoLogger('User logged in.');


warnLogger('API response is slow.');
errorLogger('Failed to fetch data.');

Real-World Coding Challenges

1. Idempotent Function Creator: Write a function once that takes another function as an
argument and returns a new function. The new function, when called, should execute the
original function only the first time it's called. Subsequent calls should do nothing. This
requires a closure to remember whether the function has already been run.
2. Private User Profile: Create a function that returns a user profile object. This object
should have public methods like getName() and getAge(), but the actual name and age
data should be stored in private variables within a closure, inaccessible from the outside.
3. Event Listener Factory: Write a function createEventListener(element, eventType) that
returns another function. The returned function should take a callback and attach it as
an event listener to the specified element for the given eventType. This demonstrates
how closures can be used to pre-configure event handling logic.
4. Caching/Memoization: Implement a function memoize that takes a function as an
argument. It returns a new function that caches the results of the original function. When
the new function is called with a set of arguments, it first checks if the result for these
arguments is already in the cache. If so, it returns the cached result; otherwise, it
computes the result, stores it in the cache (which is a closed-over variable), and then
returns it.

3.3 The this Keyword: A Deep Dive into Context

The this keyword in JavaScript is a frequent source of confusion because its value is dynamic.
It is determined not by where a function is defined, but by how it is invoked—its "call-site".30
Understanding the rules that govern its value is critical for object-oriented programming and
interacting with many browser APIs.

There is a clear order of precedence for determining the value of this:


1. New Binding: Called with new? this is the newly constructed object.
2. Explicit Binding: Called with .call(), .apply(), or .bind()? this is the object passed as the
first argument.
3. Implicit Binding: Called as a method ([Link]())? this is the object that owns the
method (the object before the dot).
4. Default Binding: None of the above? this is the global object (window) in non-strict
mode, or undefined in strict mode.

Implementation: Demonstrating the Binding Rules

JavaScript

// 1. Global Context (Default Binding in non-strict mode)


[Link](this); // In a browser, this logs the 'window' object

function showThis() {
'use strict';
[Link](this);
}
showThis(); // undefined (Default Binding in strict mode)

// 2. Implicit/Method Binding
const user = {
name: 'Alice',
greet: function() {
[Link](`Hello, my name is ${[Link]}.`);
}
};
[Link](); // 'this' refers to 'user'. Logs "Hello, my name is Alice."

// 3. Explicit Binding [Link]()


const anotherUser = { name: 'Bob' };
[Link](anotherUser); // Temporarily sets 'this' to 'anotherUser'. Logs "Hello, my name is
Bob."
// 4. New Binding with a Constructor
function Person(name) {
[Link] = name;
}
const person1 = new Person('Charlie'); // 'this' inside Person refers to the new object being created.
[Link]([Link]); // "Charlie"

// Arrow functions have no 'this' binding of their own. They use the 'this' of the enclosing lexical scope.
const car = {
brand: 'Ford',
start: function() {
[Link](`Starting the ${[Link]}`);
setTimeout(() => {
// 'this' is lexically inherited from the 'start' method's scope
[Link](`Engine of ${[Link]} is running.`);
}, 500);
}
};
[Link]();

The this Keyword Context Matrix

Invocation Method this Value (Non- this Value (Strict Example


Strict) Mode)

Global Scope Global Object Global Object [Link](this);


(window) (window)

Simple Function Global Object undefined myFunction();


Call (window)

Method Call The object before The object before [Link]();


the dot the dot

Constructor Call The newly created The newly created new


instance instance MyConstructor();

Arrow Function Lexically inherited Lexically inherited const fn = () =>


this;

Explicit Binding The object passed The object passed [Link](obj);


as 1st arg as 1st arg [Link](obj);
[Link](obj);

Real-World Coding Challenges

1. Method Borrowing: Create two distinct objects, personA and personB. personA should
have a method that uses this to introduce itself. Use .call() or .apply() to make personB
"borrow" and execute personA's method.
2. Event Handler Context: Create a button in an HTML file. Add a click event listener using
a traditional function and log this. Then, add another listener using an arrow function and
log this. Explain the difference in the console output.
3. Bound Function: Create an object with a method that logs a property of that object.
Extract that method into a standalone variable and call it, showing that this is lost. Then,
create a "bound" version of the method using .bind() that correctly maintains its this
context, even when called as a standalone function.
4. Constructor this: Write a Counter constructor function. It should initialize a count
property on this to 0 and have an increment method on its prototype that increases
[Link]. Instantiate the counter and call the increment method multiple times, logging
the count to verify that this correctly refers to the instance.

Section 4: Object-Oriented Programming in


JavaScript

JavaScript's approach to Object-Oriented Programming (OOP) is unique, built upon a


foundation of prototypal inheritance. While modern ES6 class syntax provides a more
familiar structure for developers coming from classical OOP languages like Java or C++, it is
fundamentally "syntactic sugar" over this underlying prototypal system. A deep
understanding requires grasping both the foundational mechanism and the modern
abstraction.

4.1 Prototypal Inheritance and the Prototype Chain

In JavaScript, objects can inherit properties and methods directly from other objects. Every
object has a hidden internal property, [[Prototype]], which is a link to another object. When
you try to access a property on an object, and it doesn't exist on the object itself, the
JavaScript engine looks up the prototype chain via this link.16 This process continues until
the property is found or the end of the chain is reached (

null).

Implementation: Creating Inheritance with [Link]()

The modern, standard way to create an object that inherits from another is [Link]().
This method creates a new object with its [[Prototype]] link pointing to the object provided as
its first argument.16

JavaScript

const animal = {
isAlive: true,
speak() {
[Link]("The animal makes a sound.");
}
};

const dog = [Link](animal);


[Link] = 'Golden Retriever';
[Link] = function() { // Method overriding
[Link]("Woof!");
};
[Link]([Link]); // "Golden Retriever" (own property)
[Link](); // "Woof!" (own method, overrides prototype's)
[Link]([Link]); // true (inherited from animal prototype)

const cat = [Link](animal);


[Link](); // "The animal makes a sound." (inherited method)

Constructor Functions and the prototype Property

Before ES6 classes, constructor functions were the primary way to create objects of a similar
type. Every JavaScript function has a prototype property, which is an object. When you
create a new object using a function as a constructor (with the new keyword), the new
object's [[Prototype]] is linked to the constructor function's prototype object.34

Implementation: Constructor and Prototype

JavaScript

// Constructor function
function Vehicle(make, model) {
[Link] = make;
[Link] = model;
}

// Add a method to the prototype. This is shared by all instances.


[Link] = function() {
return `${[Link]} ${[Link]}`;
};

const car = new Vehicle('Honda', 'Civic');


const truck = new Vehicle('Ford', 'F-150');

[Link]([Link]()); // "Honda Civic"


[Link]([Link]()); // "Ford F-150"

// The 'getDetails' method exists on the prototype, not on the instances themselves.
[Link]([Link]('getDetails')); // false
[Link]([Link]('getDetails')); // true
4.2 ES6 Classes: Syntactic Sugar Over Prototypes

ES6 class syntax provides a cleaner, more intuitive way to work with objects and inheritance.
It abstracts away the direct manipulation of the prototype property but achieves the exact
same result under the hood.36 Understanding that a

class is just a special kind of function is key to demystifying its behavior.

Implementation: class, constructor, and extends

The following code is a modern, class-based equivalent of the Vehicle constructor function
example.

JavaScript

class Vehicle {
constructor(make, model) {
[Link] = make;
[Link] = model;
}

getDetails() {
return `${[Link]} ${[Link]}`;
}
}

// Inheritance with 'extends' and 'super'


class Car extends Vehicle {
constructor(make, model, year) {
// 'super()' calls the parent constructor. It must be called before using 'this'.
super(make, model);
[Link] = year;
}
// Overriding the parent method
getDetails() {
// '[Link]()' calls the parent's method
return `${[Link]} ${[Link]()}`;
}
}

const myCar = new Car('Toyota', 'Camry', 2021);


[Link]([Link]()); // "2021 Toyota Camry"

Static and Private Members

Modern classes also support static methods (which belong to the class itself, not instances)
and true private fields (using the # prefix) for better encapsulation.37

Implementation: Static and Private Fields

JavaScript

class Database {
// Private field
#connectionString;

// Static property
static supportedDialects =;

constructor(connectionString) {
this.#connectionString = connectionString;
}

connect() {
// The private field is accessible inside the class
[Link](`Connecting to ${this.#connectionString}`);
}

// Static method
static isSupported(dialect) {
return [Link](dialect);
}
}

const db = new Database('user:pass@host:port/db');


[Link]();
// [Link](db.#connectionString); // SyntaxError: Private field must be declared in an enclosing
class

[Link]([Link]('PostgreSQL')); // true
[Link]([Link]('MongoDB')); // false

Real-World Coding Challenges

1. Prototype-Based Inheritance: Create a Person constructor function with name and


age properties. Add a greet method to its prototype. Then, create a Developer
constructor that inherits from Person and adds a language property. The Developer
should be able to use the greet method. Implement this without using the class keyword.
2. Refactor to ES6 Class: Take the Person and Developer constructor functions from the
previous challenge and refactor them into ES6 classes using class, extends, and super.
3. The Prototype Chain: Create a chain of three objects: grandparent, parent, and child,
where each inherits from the one before it using [Link](). Place a different
property on each object. Then, on the child object, access all three properties to
demonstrate that the prototype chain is working correctly.
4. Static Class Method: Create a User class with a password property. Add a static
method [Link](password) that checks if a password meets certain
criteria (e.g., minimum length, contains a number). This method should be callable on the
class itself, not on an instance.
5. Private Class Fields: Design a BankAccount class. The account balance should be a
private field (#balance). Provide public methods like deposit(amount),
withdraw(amount), and getBalance() to interact with the private balance, ensuring that
the balance cannot be modified directly from outside the class.

Section 5: Asynchronous JavaScript - Handling the


Non-Blocking World
JavaScript is a single-threaded language, meaning it can only execute one piece of code at a
time. However, web applications must remain responsive to user input even while performing
long-running tasks like fetching data from a server. Asynchronous programming is the
mechanism that allows JavaScript to handle these operations without freezing the main
thread.40 This section traces the evolution of asynchronous patterns in JavaScript, from
callbacks to Promises and the modern

async/await syntax.

5.1 The Event Loop Demystified: Concurrency in a Single Thread

The JavaScript runtime environment uses a model called the Event Loop to manage
asynchronous operations. This model consists of several key components 42:

1. Call Stack: A Last-In, First-Out (LIFO) stack where function calls are executed.
Synchronous code is pushed onto the stack, executed, and popped off.
2. Web APIs (or Background Tasks): Provided by the browser or [Link] environment.
When an asynchronous operation like setTimeout or fetch is called, it is handed off to
these APIs to be handled outside the main thread.
3. Task Queue (or Macrotask Queue): A First-In, First-Out (FIFO) queue where callbacks
from completed macrotasks (e.g., setTimeout, setInterval, I/O, UI events) are placed.
4. Microtask Queue: A high-priority FIFO queue for callbacks from completed microtasks,
primarily promise resolutions (.then(), .catch(), .finally()) and queueMicrotask().

The Event Loop's job is to continuously check if the Call Stack is empty. If it is, it will first
process all tasks in the Microtask Queue before moving a single task from the Task Queue to
the Call Stack for execution.42 This priority of the Microtask Queue is crucial for
understanding the precise execution order of modern asynchronous code.

Implementation: Visualizing the Event Loop

This code snippet demonstrates the execution order determined by the Event Loop and the
priority of the Microtask Queue.

JavaScript
[Link]('1. Sync: Start');

setTimeout(() => {
[Link]('4. Macrotask: setTimeout callback');
}, 0);

[Link]().then(() => {
[Link]('3. Microtask: [Link] callback');
});

[Link]('2. Sync: End');

// --- Execution Order ---


// 1. 'Sync: Start' is logged.
// 2. setTimeout(..., 0) is called. The callback is sent to the Web API and then placed in the Macrotask
Queue.
// 3. [Link]().then(...) is called. The callback is placed in the Microtask Queue.
// 4. 'Sync: End' is logged.
// 5. The Call Stack is now empty.
// 6. The Event Loop checks the Microtask Queue first. It finds the promise callback and executes it,
logging '3. Microtask...'.
// 7. The Microtask Queue is now empty. The Event Loop checks the Macrotask Queue. It finds the
setTimeout callback and executes it, logging '4. Macrotask...'.

5.2 The Evolution to Promises: From Callback Hell to Chainable


Futures

The original way to handle asynchronous operations was with callbacks—functions passed
as arguments to be executed upon completion. For sequential operations, this led to deeply
nested code known as "callback hell," which was difficult to read, maintain, and debug.44

Promises were introduced in ES6 to solve this problem. A Promise is an object that
represents the eventual completion (or failure) of an asynchronous operation. It can be in one
of three states: pending, fulfilled, or rejected.45

Promises allow you to attach callbacks using the .then() (for fulfillment) and .catch() (for
rejection) methods. Crucially, these methods themselves return a new promise, enabling
chaining. This transforms nested code into a flat, readable sequence and provides a
centralized way to handle errors.45
Implementation: Fetching Data with Promises

JavaScript

const API_URL = '[Link]

fetch(API_URL)
.then(response => {
// Check if the HTTP response is successful
if (![Link]) {
throw new Error(`HTTP error! Status: ${[Link]}`);
}
return [Link](); //.json() also returns a promise
})
.then(user => {
[Link]('User Name:', [Link]);
})
.catch(error => {
[Link]('Failed to fetch user:', error);
})
.finally(() => {
[Link]('Fetch attempt finished.');
});

Concurrent Operations with [Link]()

To run multiple asynchronous operations in parallel and wait for all of them to complete,
[Link]() is used. It takes an array of promises and returns a single promise that fulfills
with an array of the results.45

JavaScript

const userPromise = fetch('[Link] => [Link]());


const postsPromise = fetch('[Link] => [Link]());
[Link]([userPromise, postsPromise])
.then(([user, post]) => {
[Link](`User ${[Link]} wrote post: "${[Link]}"`);
})
.catch(error => {
[Link]('Failed to fetch data:', error);
});

5.3 Mastering async/await: Synchronous-Style Asynchronous Code

Introduced in ES2017, async/await is syntactic sugar built on top of Promises. It allows you to
write asynchronous code that looks and behaves more like synchronous code, making it
significantly easier to read and reason about.45

● The async keyword before a function declaration makes it automatically return a


promise.
● The await keyword can only be used inside an async function. It pauses the function's
execution until the promise it's waiting on is settled.

Implementation: Refactoring with async/await

The previous fetch example can be rewritten with async/await for improved clarity, especially
for error handling with standard try...catch blocks.

JavaScript

async function fetchUserData() {


const API_URL = '[Link]
[Link]('Fetching data...');

try {
const response = await fetch(API_URL);

if (![Link]) {
throw new Error(`HTTP error! Status: ${[Link]}`);
}
const user = await [Link]();
[Link]('User Name:', [Link]);
} catch (error) {
[Link]('Failed to fetch user:', error);
} finally {
[Link]('Fetch attempt finished.');
}
}

fetchUserData();

While async/await makes code appear synchronous, it is crucial to remember that it is still
non-blocking. The await keyword only pauses the execution within that specific async
function, allowing the Event Loop to continue running other tasks.

Real-World Coding Challenges

1. Event Loop Order: Given a script with [Link], setTimeout(..., 0),


[Link]().then(...), and another [Link], predict the exact order of the
output and explain your reasoning based on the Call Stack, Microtask Queue, and
Macrotask Queue.
2. Callback to Promise Refactor: Convert a hypothetical function that uses nested
callbacks (e.g., getData(id, (user) => { getPosts([Link], (posts) => {... }) })) into a modern
promise chain using .then() and .catch().
3. Concurrent API Calls: Write an async function that takes an array of user IDs. Use
[Link]() and fetch to retrieve the data for all users concurrently. The function should
return an array of user objects.
4. Sequential async/await: Write an async function that first fetches a user's data, then
uses that user's ID to fetch their posts in a separate API call. This demonstrates a
sequential asynchronous workflow using await. Handle potential errors at each step
using a try...catch block.
5. Promise Race: Create a function fetchWithTimeout(url, duration) that uses
[Link]() to fetch data from a URL. If the fetch request does not complete within
the specified duration, the promise should reject with a "Timeout" error.

Section 6: Advanced Language Features and


Architecture

This section covers modern, advanced topics crucial for building large-scale, modular, and
maintainable full-stack applications. These concepts are often what separate senior
candidates from mid-level ones, demonstrating a deep understanding of JavaScript's
capabilities and the architectural patterns used in professional software engineering.

6.1 ES Modules: Structuring Modern Applications

ES Modules (ESM) are the native module system in JavaScript, providing a standardized way
to organize code into reusable, self-contained files. This is essential for managing complexity
in large applications.48

● export: Used to expose functions, classes, or variables from a module. A module can
have multiple named exports and at most one default export.48
● import: Used to bring exported features into another module.48
● Dynamic import(): A function-like import() expression that loads a module on demand
and returns a promise. This is the key to implementing code-splitting, a performance
optimization technique where code is loaded only when it's needed.17

A key advantage of ES Modules is that they are statically analyzable. This means that the
dependency graph of an application can be determined at build time, before the code is
executed. This static nature enables powerful optimizations by build tools like Webpack, most
notably tree-shaking—the process of eliminating unused code from the final bundle, which
significantly reduces application size and improves load times.50

Implementation: Named and Default Exports

JavaScript

// 📁 utils/[Link] (Module with named exports)


export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;
// 📁 utils/[Link] (Module with a default export)
export default function log(message) {
[Link](`[LOG]: ${message}`);
}

// 📁 [Link] (Consuming module)


import customLogger from './utils/[Link]'; // Default import can be named anything
import { add, subtract as minus } from './utils/[Link]'; // Named imports, with renaming

customLogger('Application starting...');
const sum = add(10, 5);
const difference = minus(10, 5);

[Link](`Sum: ${sum}, Difference: ${difference}`);

Implementation: Dynamic Import for Code-Splitting

In a web application, you might only load a complex charting library when the user clicks a
button to view a report.

JavaScript

// 📁 [Link]
const reportButton = [Link]('report-btn');

[Link]('click', async () => {


try {
// Dynamically import the charting module only when needed
const { Chart } = await import('./modules/[Link]');
const chart = new Chart(/*... */);
[Link]();
} catch (error) {
[Link]('Failed to load charting module', error);
}
});

Real-World Coding Challenges


1. Module Refactoring: Take a single, large JavaScript file with multiple functions and
classes and refactor it into several smaller modules. Create a [Link] file that imports the
necessary pieces from each module to restore the original functionality.
2. Named vs. Default Export: Create a module that exports a primary class as a default
export and several utility functions as named exports. Write another module that imports
and uses both the default and named exports.
3. Dynamic Module Loading: Build a simple web page with two buttons: "Show Map" and
"Show Chart". Write JavaScript that dynamically imports a mapping library when the first
button is clicked and a charting library when the second is clicked, and then renders the
respective UI element.
4. Module Aggregator: Create an "aggregator" module (e.g., api/[Link]) that imports
functions from several other modules (e.g., api/[Link], api/[Link]) and re-exports
them as a single, unified API object. This is a common pattern for organizing API clients.

6.2 Iterators and Generators: Custom Iteration and Advanced Control


Flow

ES6 introduced a standardized protocol for iteration, allowing any object to define its own
iteration behavior.
● Iterator Protocol: An object is an iterator if it has a .next() method that returns an
object of the form { value, done }.52
● Iterable Protocol: An object is iterable if it implements a `` method that returns an
iterator. This makes it compatible with constructs like the for...of loop and the spread
operator (...).52
● Generators: A special kind of function, declared with function*, that can be paused and
resumed. When called, a generator returns an iterator. The yield keyword pauses the
generator and returns a value.52

Implementation: A Custom Iterable Range Object

JavaScript

class Range {
constructor(start, end) {
[Link] = start;
[Link] = end;
}

// Make the class iterable


() {
let current = [Link];
const end = [Link];

// Return the iterator object


return {
next() {
if (current <= end) {
return { value: current++, done: false };
} else {
return { done: true };
}
}
};
}
}

const myRange = new Range(1, 5);


for (const num of myRange) {
[Link](num); // Logs 1, 2, 3, 4, 5
}

Implementation: The Same Range with a Generator

Generators provide a much simpler syntax for creating iterators by managing the state
automatically.

JavaScript

function* rangeGenerator(start, end) {


for (let i = start; i <= end; i++) {
yield i;
}
}

const myGenRange = rangeGenerator(1, 5);


for (const num of myGenRange) {
[Link](num); // Logs 1, 2, 3, 4, 5
}

Generators are powerful for lazy evaluation—generating values only when they are
requested. This is highly memory-efficient for handling large or even infinite data streams.52

Real-World Coding Challenges

1. Custom Iterable Data Structure: Create a LinkedList class. Implement the `` method
on this class so that you can iterate over the list's nodes using a for...of loop.
2. Infinite Sequence Generator: Write a generator function that yields the Fibonacci
sequence indefinitely. Use it to print the first 10 Fibonacci numbers.
3. Asynchronous Generator: Write an async generator function that fetches pages of
data from a paginated API. Each yield should return the data from one page. Use a for
await...of loop to consume the data from the generator.
4. Two-Way Communication: Create a generator function that yields a question (e.g.,
"What is your name?"). Use the .next(value) method to pass an answer back into the
generator, which then yields a new question based on the previous answer.

6.3 Meta-programming with Proxies and Reflect

Meta-programming is the concept of writing code that can inspect, modify, or generate
other code. In JavaScript, the Proxy and Reflect objects, introduced in ES6, provide powerful
tools for meta-programming.54

● Proxy: Creates a wrapper around an object (the "target") that can intercept
fundamental operations like property access (get), assignment (set), or function calls
(apply). These interceptions are handled by "traps" defined in a handler object.54
● Reflect: A built-in object that provides static methods for the same fundamental
operations that proxies can intercept. It is often used within proxy traps to forward the
operation to the target object in a standardized way.54
This capability is used by modern frameworks like [Link] to create their reactivity systems,
allowing them to automatically detect state changes and update the UI without requiring
developers to call special setter functions.56

Implementation: Validation with a Proxy

This example creates a proxy that validates data before setting it on an object.

JavaScript

const user = {
name: 'John Doe',
age: 30
};

const validator = {
set(target, property, value) {
if (property === 'age') {
if (typeof value!== 'number' |

| value < 18) {


throw new TypeError('Age must be a number and at least 18.');
}
}
// Forward the operation to the original object
return [Link](target, property, value);
}
};

const userProxy = new Proxy(user, validator);

[Link] = 25; // Works


[Link]([Link]); // 25

// [Link] = 'twenty'; // Throws TypeError: Age must be a number and at least 18.
// [Link] = 17; // Throws TypeError: Age must be a number and at least 18.
Real-World Coding Challenges

1. Logging Proxy: Create a generic loggingProxy function that takes an object and returns
a proxy. The proxy should log a message to the console every time a property is read
(get) or written (set).
2. Read-Only View: Write a function that takes an object and returns a read-only proxy of
it. If any code attempts to set a property or delete a property on the proxy, it should
throw an error.
3. API Caching Proxy: Create a proxy for an object that has an async method
fetchData(id). The proxy's get trap should intercept calls to this method. The first time
fetchData is called with a specific id, it should perform the network request. Subsequent
calls with the same id should return a cached result instead of making another network
request.
4. Default Value Proxy: Implement a proxy that provides a default value for any property
that does not exist on the target object. For example, if [Link] is
accessed, it should return 'default value' instead of undefined.

6.4 Memory Management and Garbage Collection

While JavaScript's memory management is automatic, understanding the fundamentals is


crucial for writing performant, leak-free applications, especially for long-running SPAs or
[Link] servers.6

● Memory Lifecycle: Allocation, Use, and Release.57


● Stack and Heap: Primitives and function call frames are stored on the fast, fixed-size
stack. Objects and other reference types are stored on the larger, more dynamic heap.6
● Garbage Collection (GC): The process of automatically reclaiming memory occupied by
objects that are no longer in use.57
● Mark-and-Sweep Algorithm: The primary algorithm used by modern JavaScript
engines. The garbage collector starts from a set of "root" objects (like the global object)
and traverses all object references, "marking" every object it can reach. In the "sweep"
phase, all unmarked objects are considered unreachable and their memory is reclaimed.6

Memory Leaks occur when objects are no longer needed by the application but are still
"reachable" from a root, preventing the garbage collector from freeing their memory.
Common causes include:
● Accidental Global Variables: Undeclared variables that become properties of the
global object.
● Forgotten Timers or Callbacks: setInterval callbacks that are never cleared.
● Detached DOM Elements: DOM nodes that are removed from the page but still have
references to them in JavaScript code.
● Closures: Closures that hold references to large objects longer than necessary.6

Implementation: Simulating a Memory Leak with a Closure

JavaScript

// This function creates a memory leak if not handled properly.


function setupLeakyListener() {
const largeObject = new Array(1e6).fill('some data');

// An element that might be removed from the DOM later


const element = [Link]('my-button');

if (element) {
// The callback closure holds a reference to largeObject.
[Link]('click', () => {
[Link]('Button clicked!');
// Even if the button is removed, this listener might keep 'largeObject' in memory.
});
}

// To prevent the leak, one would need to call removeEventListener


// when the element is no longer needed.
}

Real-World Coding Challenges

1. Identify the Leak: Analyze a piece of code containing a setInterval that repeatedly
creates objects and pushes them into an array that is never cleared. Explain why this
constitutes a memory leak.
2. Detached DOM Node: Write a script that creates a large number of DOM elements,
appends them to a list, and then clears the list by setting its innerHTML to ''. However,
keep references to those elements in a JavaScript array. Explain why this prevents the
elements from being garbage collected.
3. Event Listener Cleanup: Create a simple single-page application component (e.g., a
custom class or function). In its "mount" logic, add an event listener to the window
object. Implement a "unmount" or cleanup function that correctly removes the event
listener to prevent a memory leak.
4. WeakMap for Caching: Demonstrate the difference between Map and WeakMap for
caching data associated with objects. Create an object, use it as a key in both a Map and
a WeakMap, then remove all other references to the object. Explain why the object can
be garbage-collected when using WeakMap but not with Map.

6.5 Essential JavaScript Design Patterns

Design patterns are reusable, well-documented solutions to common problems in software


design. Understanding them provides a high-level vocabulary for discussing software
architecture and helps in building maintainable, scalable systems.60

Singleton Pattern

Ensures that a class has only one instance and provides a single, global point of access to it.
● Real-World Use Case: Managing a shared resource, such as a single database
connection pool, a global application configuration object, or a logging service.62

Implementation: A Configuration Manager

JavaScript

const ConfigManager = (function() {


let instance;
let config = { theme: 'dark', version: '1.0.0' };

function createInstance() {
return {
getConfig: () => config,
set: (key, value) => { config[key] = value; }
};
}

return {
getInstance: function() {
if (!instance) {
instance = createInstance();
}
return instance;
}
};
})();

const config1 = [Link]();


const config2 = [Link]();

[Link](config1 === config2); // true


[Link]('theme', 'light');
[Link]([Link]().theme); // 'light'

Factory Pattern

Provides an interface for creating objects but allows the logic to decide which class to
instantiate. This decouples the client code from the specific classes it needs to create.64

● Real-World Use Case: Creating different types of user objects (Admin, Editor, Guest)
based on a role string, or instantiating different UI components from a component
library.67

Implementation: A Vehicle Factory

JavaScript
class Car {
drive() { [Link]('Driving a car.'); }
}

class Truck {
drive() { [Link]('Driving a truck.'); }
}

class VehicleFactory {
createVehicle(type) {
switch (type) {
case 'car':
return new Car();
case 'truck':
return new Truck();
default:
throw new Error('Unknown vehicle type');
}
}
}

const factory = new VehicleFactory();


const myCar = [Link]('car');
[Link](); // "Driving a car."

Observer Pattern (Publish/Subscribe)

Defines a one-to-many dependency between objects. When one object (the "subject" or
"publisher") changes state, all its dependents (the "observers" or "subscribers") are notified
and updated automatically.69

● Real-World Use Case: This is the foundational pattern for browser event listeners
(addEventListener) and is at the core of state management libraries like Redux. When the
Redux store (the subject) updates, all subscribed React components (the observers) are
notified to re-render.71

Implementation: A Simple News Agency


JavaScript

class NewsAgency { // The Subject


constructor() {
[Link] =;
}

subscribe(subscriber) {
[Link](subscriber);
}

unsubscribe(subscriber) {
[Link] = [Link](s => s!== subscriber);
}

publish(news) {
[Link](subscriber => [Link](news));
}
}

class NewsChannel { // An Observer


constructor(name) {
[Link] = name;
}

update(news) {
[Link](`[${[Link]}] Breaking News: ${news}`);
}
}

const agency = new NewsAgency();

const channel1 = new NewsChannel('CNN');


const channel2 = new NewsChannel('BBC');

[Link](channel1);
[Link](channel2);

[Link]('A new JavaScript feature has been announced!');


// [CNN] Breaking News: A new JavaScript feature has been announced!
// Breaking News: A new JavaScript feature has been announced!

Real-World Coding Challenges

1. Singleton Logger: Implement a Logger class as a singleton. It should have a


log(message) method and an getLogs() method. Ensure that no matter how many times
the logger is "created," all log messages go to the same instance.
2. UI Component Factory: Write a factory function createUIElement(type, text) that
returns different HTML element objects based on the type string (e.g., 'button', 'p', 'h1').
3. Observer for a Shopping Cart: Create a ShoppingCart subject and a HeaderIcon
observer. The ShoppingCart should notify the HeaderIcon whenever an item is added, so
the icon can update its display with the new total number of items.
4. Combining Patterns: Create a system where a UserFactory creates User objects. Each
User object is a "subject" in the Observer pattern. Create an AuditService observer that
subscribes to every new user created by the factory and logs any changes to the user's
properties (e.g., name or email changes).

Section 7: Essential APIs and Error Handling

Building real-world applications requires interacting with external resources and gracefully
handling unexpected issues. This section covers the modern Fetch API for making network
requests and the standard mechanisms for robust error handling.

7.1 Making Network Requests with the Fetch API

The Fetch API provides a modern, promise-based interface for making network requests. It is
the standard for fetching resources (like JSON data from an API) in both browsers and
[Link] environments.72

Making a GET Request


The fetch() function takes the URL of the resource you want to retrieve as its primary
argument and returns a promise that resolves to the Response object.

Implementation: Fetching User Data

JavaScript

const apiUrl = '[Link]

fetch(apiUrl)
.then(response => {
// Check if the request was successful (status code 200-299)
if (![Link]) {
throw new Error(`Network response was not ok: ${[Link]}`);
}
return [Link](); // Parses the JSON body text as a JavaScript object
})
.then(data => {
[Link]('User data:', data);
})
.catch(error => {
[Link]('There was a problem with the fetch operation:', error);
});

Making a POST Request

To send data to a server, you can use a POST request. This requires passing a second
argument to fetch(): an options object where you can specify the method, headers, and body
of the request.72

Implementation: Creating a New Post


JavaScript

const postUrl = '[Link]

const newPost = {
title: 'A New Post',
body: 'This is the content of the new post.',
userId: 1
};

fetch(postUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json' // Tells the server we are sending JSON data
},
body: [Link](newPost) // Converts the JavaScript object to a JSON string
})
.then(response => [Link]())
.then(data => {
[Link]('Success:', data);
})
.catch(error => {
[Link]('Error:', error);
});

Real-World Coding Challenges

1. Get All Posts: Fetch and log all posts from [Link]
2. Create and Verify: Write an async/await function that first POSTs a new comment to
[Link] then immediately makes a GET request
to retrieve that same comment by its new ID to verify it was created.
3. Custom Headers: Make a GET request and include a custom X-Custom-Header with a
value of your choice. Log the response body to verify the server received it.
4. API Error Handling: Write a fetch request to a non-existent URL. Use .catch() to handle
the network error and display a user-friendly message to the console.
7.2 Robust Error and Exception Handling

Proper error handling is crucial for building reliable applications. JavaScript provides the
try...catch...finally statement to handle runtime errors (exceptions) without crashing the
program.74

● try: The try block contains code that might throw an error.
● catch: The catch block is executed if an error is thrown in the try block. It receives an
error object containing details about the exception.
● throw: The throw statement allows you to create and throw custom errors.
● finally: The finally block contains code that will execute regardless of whether an error
was thrown or caught. It is ideal for cleanup tasks, like closing a file or a network
connection.74

Implementation: Parsing Potentially Invalid JSON

A common real-world scenario is parsing JSON data received from an external source, which
may not be correctly formatted.75

JavaScript

const potentiallyBadJson = '{"name": "Alice", "age": 30,}'; // Invalid JSON (trailing comma)

try {
[Link]('Attempting to parse JSON...');
const user = [Link](potentiallyBadJson);
[Link]('Parsed successfully:', user);
} catch (error) {
[Link]('An error occurred during parsing!');
[Link]('Error Name:', [Link]); // e.g., "SyntaxError"
[Link]('Error Message:', [Link]); // e.g., "Unexpected token } in JSON at position..."
} finally {
[Link]('Parsing attempt finished.');
}

Implementation: Custom Errors


You can throw your own errors to signal specific problems in your application logic.

JavaScript

function calculateBmi(weight, height) {


if (height <= 0) {
throw new Error('Height must be a positive number.');
}
return weight / (height * height);
}

try {
const bmi = calculateBmi(70, 0);
[Link](`Your BMI is ${bmi}`);
} catch (error) {
[Link]('Calculation failed:', [Link]);
}

Real-World Coding Challenges

1. API Response Validator: Write a function that takes a fetch response object. Inside a
try block, check if [Link] is true. If not, throw a new Error with the status text. Call
this function within a fetch chain and use .catch() to handle the thrown error.
2. Input Validation: Create a function that accepts a user object. Use a try block to access
[Link]. If user or [Link] is null or undefined, it will throw a TypeError.
Catch this specific error and return a default email address.
3. Resource Cleanup: Write a function that simulates opening a resource (e.g.,
[Link]('Resource opened')). Inside a try...finally block, simulate doing work (which
could potentially throw an error) and ensure the resource is always closed (e.g.,
[Link]('Resource closed')) in the finally block.
4. Conditional Rethrowing: In a try...catch block, catch an error. Use an if statement
inside the catch block to check if the error is of a specific type (e.g., TypeError). If it is,
handle it. If it's any other type of error, "re-throw" it so it can be caught by a higher-level
error handler.75
7.3 The Enum Pattern for Fixed Constants

While JavaScript does not have a built-in enum type like other languages, you can simulate
one using a plain object. Enums are useful for defining a collection of named constants, which
makes code more readable and less prone to errors from magic strings or numbers.85

To ensure the "enum" cannot be modified, it is a best practice to freeze the object using
[Link]().85

Implementation: Application Status Enum

JavaScript

const AppStatus = [Link]({


PENDING: 'PENDING',
LOADING: 'LOADING',
SUCCESS: 'SUCCESS',
FAILED: 'FAILED'
});

function handleApiResponse(status) {
switch (status) {
case [Link]:
[Link]('Showing spinner...');
break;
case [Link]:
[Link]('Displaying data...');
break;
case [Link]:
[Link]('Showing error message...');
break;
default:
[Link]('Waiting...');
}
}
Works cited

1. Variables - The Modern JavaScript Tutorial, accessed August 23, 2025,


[Link]
2. Grammar and types - MDN - Mozilla, accessed August 23, 2025,
[Link]
types
3. Data types - The Modern JavaScript Tutorial, accessed August 23, 2025,
[Link]
4. JavaScript Data Types: 27 Quick Questions You Need To Master - DEV
Community, accessed August 23, 2025,
[Link]
need-to-master-1828
5. Day 02: Variables and Data Types in JavaScript || 40 Days of JS - YouTube,
accessed August 23, 2025, [Link]
6. Memory Management in JavaScript - GeeksforGeeks, accessed August 23, 2025,
[Link]
7. JavaScript Data Types (with Examples) - Programiz, accessed August 23, 2025,
[Link]
8. JavaScript data types and data structures - MDN - Mozilla, accessed August 23,
2025,
[Link]
9. Expressions and operators - MDN, accessed August 23, 2025,
[Link]
d_operators
10. JavaScript Operators (with Examples) - Programiz, accessed August 23, 2025,
[Link]
11. JavaScript Operators, Loops, and Flow Control: A Comprehensive Guide - DEV
Community, accessed August 23, 2025, [Link]
operators-loops-and-flow-control-a-comprehensive-guide-1a5m
12. JavaScript Operators Explained: From Basics to Advanced Tricks | by Iqbal
Rosyidi | Medium, accessed August 23, 2025, [Link]
rosyidi/javascript-operators-explained-from-basics-to-advanced-tricks-
e2d2578dcd3f
13. JavaScript Control Flow Examples - GeeksforGeeks, accessed August 23, 2025,
[Link]
14. Control flow - MDN - Mozilla, accessed August 23, 2025,
[Link]
15. JavaScript Control Flow: if, else, switch, for, while | Codeguage, accessed August
23, 2025, [Link]
16. Prototypal inheritance - The Modern JavaScript Tutorial, accessed August 23,
2025, [Link]
17. JavaScript Guide - MDN - Mozilla, accessed August 23, 2025,
[Link]
18. Guide to JavaScript data structures (arrays, sets, maps) - DEV ..., accessed
August 24, 2025, [Link]
structures-arrays-sets-maps-1o09
19. [Link]() - MDN, accessed August 24, 2025,
[Link]
Global_Objects/Array/map
20. JavaScript Array methods: Filter, Map, Reduce, and Sort - DEV ..., accessed
August 24, 2025, [Link]
reduce-and-sort-32m5
21. [Link]() - MDN - Mozilla, accessed August 24, 2025,
[Link]
Global_Objects/Array/reduce
22. Inheritance and the prototype chain - MDN - Mozilla, accessed August 23, 2025,
[Link]
_the_prototype_chain
23. Map and Set - The Modern JavaScript Tutorial, accessed August 24, 2025,
[Link]
24. Set vs Map in JavaScript - GeeksforGeeks, accessed August 24, 2025,
[Link]
25. JavaScript Functions and Scope – a Beginner's Guide, accessed August 23, 2025,
[Link]
26. JavaScript Functions and Scope Explained: Master Reusable Code and Closures -
Medium, accessed August 23, 2025,
[Link]
explained-master-reusable-code-and-closures-81589c7e378b
27. Closures - MDN - Mozilla, accessed August 23, 2025,
[Link]
28. What is a practical use for a closure in JavaScript? - Stack Overflow, accessed
August 23, 2025, [Link]
practical-use-for-a-closure-in-javascript
29. What is the practical use for a closure in JavaScript? - GeeksforGeeks, accessed
August 23, 2025, [Link]
practical-use-for-a-closure-in-javascript/
30. JavaScript - MDN - Mozilla, accessed August 23, 2025,
[Link]
Operators/this
31. How to Use the "this" Keyword in JavaScript - freeCodeCamp, accessed August
23, 2025, [Link]
32. [Link]() - MDN - Mozilla, accessed August 23, 2025,
[Link]
Global_Objects/Object/create
33. Working with objects - MDN - Mozilla, accessed August 23, 2025,
[Link]
bjects
34. JavaScript prototypes and inheritance simplified | Launch School - Medium,
accessed August 23, 2025, [Link]
overview-of-javascript-prototypes-and-prototypical-inheritance-f00c7af8a93c
35. JavaScript Prototype Inheritance Explained (with Examples) - [Link],
accessed August 23, 2025, [Link]
inheritance-explained-with-examples/
36. Classes - MDN - Mozilla, accessed August 23, 2025,
[Link]
37. Classes in JavaScript - MDN - Mozilla, accessed August 23, 2025,
[Link]
Advanced_JavaScript_objects/Classes_in_JavaScript
38. A deep dive into ES6 Classes - DEV Community, accessed August 23, 2025,
[Link]
39. Using classes - MDN - Mozilla, accessed August 23, 2025,
[Link]
40. Mastering Asynchronous JavaScript: Promises, async/await, and the Event Loop
Explained, accessed August 23, 2025, [Link]
asynchronous-javascript-promises-asyncawait-and-the-event-loop-explained-
21oc
41. Introducing asynchronous JavaScript - MDN - Mozilla, accessed August 23, 2025,
[Link]
Async_JS/Introducing
42. JavaScript Event Loop: Syntax, Usage, and Examples - Mimo, accessed August
23, 2025, [Link]
43. JavaScript Event Loop Explained: A Beginner's Guide With Examples - DEV
Community, accessed August 23, 2025, [Link]
event-loop-explained-a-beginners-guide-with-examples-4kae
44. Event Loop in JavaScript - GeeksforGeeks, accessed August 23, 2025,
[Link]
45. Using promises - MDN - Mozilla, accessed August 23, 2025,
[Link]
46. How to use promises - MDN - Mozilla, accessed August 23, 2025,
[Link]
Promises
47. async function - MDN - Mozilla, accessed August 23, 2025,
[Link]
Statements/async_function
48. JavaScript modules - MDN, accessed August 23, 2025,
[Link]
49. A Guide to Modules in JavaScript - Web Reference, accessed August 23, 2025,
[Link]
50. Our Guide to Modern Front-End Build Pipelines - 57Blocks, accessed August 23,
2025, [Link]
51. 7 Essential Tools for Modern JavaScript Development - Medium, accessed
August 23, 2025, [Link]
modern-javascript-development-2217cdf6a098
52. Iterators and generators - MDN - Mozilla, accessed August 23, 2025,
[Link]
enerators
53. Iterators and Generators in Javascript | by Meet Patel | Simform ..., accessed
August 23, 2025, [Link]
generators-in-javascript-22da731b7fe3
54. Proxy - MDN - Mozilla, accessed August 23, 2025,
[Link]
Global_Objects/Proxy
55. Proxy and Reflect - [Link], accessed August 23, 2025,
[Link]
56. JavaScript Proxy Explained Clearly By Practical Examples, accessed August 23,
2025, [Link]
57. Memory management - JavaScript | MDN, accessed August 23, 2025,
[Link]
gement
58. Garbage collection - The Modern JavaScript Tutorial, accessed August 23, 2025,
[Link]
59. How does JavaScript garbage collection work? | Quiz Interview Questions with
Solutions, accessed August 23, 2025,
[Link]
collection-work
60. JavaScript Design Patterns – Explained with Examples - freeCodeCamp,
accessed August 23, 2025, [Link]
design-patterns-explained/
61. Design Patterns - [Link], accessed August 23, 2025,
[Link]
62. Object-Oriented Design Patterns with Java - freeCodeCamp, accessed August
23, 2025, [Link]
patterns-with-java/
63. JavaScript Design Patterns: A Hands-On Guide with Real-world Examples -
[Link], accessed August 23, 2025,
[Link]
64. Factory Design Pattern in JavaScript - DEV Community, accessed August 23,
2025, [Link]
65. Factory Pattern - [Link], accessed August 23, 2025,
[Link]
66. Singleton Design Pattern – How it Works in JavaScript with Example ..., accessed
August 23, 2025, [Link]
pattern-with-javascript/
67. JavaScript Factory Method Design Pattern - [Link], accessed August 23,
2025, [Link]
68. Factory Method in JavaScript | Design Pattern - GeeksforGeeks, accessed
August 23, 2025, [Link]
method-in-javascript-design-pattern/
69. Observer - [Link], accessed August 23, 2025,
[Link]
70. Observer Pattern - [Link], accessed August 23, 2025,
[Link]
71. JavaScript Observer Design Pattern - [Link], accessed August 23, 2025,
[Link]
72. Using the Fetch API - MDN - Mozilla, accessed August 24, 2025,
[Link]
73. How to send headers with JavaScript Fetch API? - ReqBin, accessed August 24,
2025, [Link]
74. try...catch - MDN - Mozilla, accessed August 24, 2025,
[Link]
Statements/try...catch
75. Error handling, "try...catch" - The Modern JavaScript Tutorial, accessed August
24, 2025, [Link]
76. Object - MDN - Mozilla, accessed August 24, 2025,
[Link]
Global_Objects/Object
77. [Link]() - MDN, accessed August 24, 2025,
[Link]
Global_Objects/Object/assign
78. [Link]() - MDN - Mozilla, accessed August 24, 2025,
[Link]
Global_Objects/Object/freeze
79. [Link]() - MDN - Mozilla, accessed August 24, 2025,
[Link]
Global_Objects/Object/seal
80. [Link]() - MDN, accessed August 24, 2025,
[Link]
Global_Objects/Array/slice
81. Array - MDN, accessed August 24, 2025,
[Link]
Global_Objects/Array
82. [Link]() - MDN, accessed August 24, 2025,
[Link]
Global_Objects/Array/splice
83. [Link]() - MDN - Mozilla, accessed August 24, 2025,
[Link]
Global_Objects/Array/forEach
84. JavaScript Array Methods: Beginners Tutorial with Examples - Full Stack
Foundations, accessed August 24, 2025,
[Link]
85. Enums in JavaScript - GeeksforGeeks, accessed August 24, 2025,
[Link]

You might also like