JavaScript Mastery

Learn JavaScript from the fundamentals to DOM manipulation, asynchronous programming, modules, APIs, and modern application patterns.

JavaScript Basics

What is JavaScript?

JavaScript is a programming language used to add logic, behavior, interaction, and dynamic content to applications.

In the browser, JavaScript can interact with HTML, CSS, browser APIs, network requests, events, storage, and the DOM.

console.log("Hello, JavaScript!");

JavaScript Mental Model

Input
  ↓
Logic
  ↓
State
  ↓
Output
const price = 100;
const quantity = 3;

const total = price * quantity;

console.log(total);

JavaScript in the Web Stack

HTML
  ↓
Structure

CSS
  ↓
Presentation

JavaScript
  ↓
Behavior + Interaction

Running JavaScript

External JavaScript

<script src="app.js"></script>

Module Script

<script type="module" src="app.js"></script>

Inline Script

<script>
  console.log("Hello");
</script>

Browser Console

JavaScript can be executed directly from the browser developer console.

2 + 2
console.log("Testing JavaScript");

Node.js

node app.js

Node.js allows JavaScript to run outside the browser.

Syntax

Statements

const name = "Alex";
console.log(name);

Comments

// Single-line comment

/*
  Multi-line comment
*/

Semicolons

const x = 10;
const y = 20;

JavaScript has automatic semicolon insertion. A consistent coding style is still important.

Case Sensitivity

const name = "Alex";
const Name = "Sam";

console.log(name);
console.log(Name);

name and Name are different identifiers.

Variables

const

const name = "Alex";

Use const when the binding should not be reassigned.

let

let count = 0;

count += 1;

Use let when the binding needs to be reassigned.

var

var oldStyle = true;

var is function-scoped and behaves differently from let and const. Modern JavaScript generally prefers let and const.

Variable Naming

const firstName = "Alex";
const userCount = 10;
const isLoggedIn = true;

Use descriptive names and follow a consistent naming convention.

Data Types

Primitive Types

const name = "Alex";       // string
const age = 25;            // number
const active = true;       // boolean
const value = undefined;   // undefined
const empty = null;        // null
const id = 123n;           // bigint
const unique = Symbol();   // symbol

Objects

const user = {
  name: "Alex",
  age: 25
};

Objects are non-primitive values and can contain properties and methods.

typeof

typeof "hello";
typeof 42;
typeof true;
typeof undefined;
typeof {};
typeof function () {};

null

const user = null;

null represents an intentional absence of a value.

undefined

let result;

console.log(result);

undefined commonly indicates that a value has not been assigned.

Operators

Arithmetic

10 + 5;
10 - 5;
10 * 5;
10 / 5;
10 % 3;
2 ** 3;

Assignment

let count = 10;

count += 5;
count -= 2;
count *= 2;
count /= 2;

Comparison

5 === 5;
5 !== 4;
5 > 3;
5 < 10;
5 >= 5;
3 <= 5;

Prefer strict equality === and strict inequality !== when comparing values.

Logical Operators

true && true;
true || false;
!true;

Nullish Coalescing

const name = userName ?? "Guest";

The right-hand value is used when the left-hand value is null or undefined.

Optional Chaining

const city = user?.address?.city;

Ternary Operator

const status =
  age >= 18
    ? "Adult"
    : "Minor";

Type Coercion

Implicit Conversion

"5" + 2;
// "52"

Explicit Conversion

Number("42");
String(42);
Boolean(1);

Truthy and Falsy

Boolean(false);
Boolean(0);
Boolean("");
Boolean(null);
Boolean(undefined);

Boolean("hello");
Boolean(42);

Strict Comparison

5 === "5";
// false

5 == "5";
// true

Understand the difference between loose equality and strict equality. Strict comparison is generally easier to reason about.

Conditionals

if

if (age >= 18) {
  console.log("Adult");
}

if / else

if (isLoggedIn) {
  console.log("Dashboard");
} else {
  console.log("Login");
}

else if

if (score >= 90) {
  console.log("A");
} else if (score >= 80) {
  console.log("B");
} else {
  console.log("C");
}

switch

switch (role) {
  case "admin":
    console.log("Full access");
    break;

  case "editor":
    console.log("Edit access");
    break;

  default:
    console.log("Read access");
}

Loops

for

for (let i = 0; i < 5; i++) {
  console.log(i);
}

while

let count = 0;

while (count < 5) {
  console.log(count);
  count++;
}

do...while

let count = 0;

do {
  console.log(count);
  count++;
} while (count < 5);

for...of

const names = ["Alex", "Sam", "Jordan"];

for (const name of names) {
  console.log(name);
}

for...in

const user = {
  name: "Alex",
  age: 25
};

for (const key in user) {
  console.log(key, user[key]);
}

for...of is generally used for iterable values, while for...in enumerates object property keys.

break and continue

for (let i = 0; i < 10; i++) {
  if (i === 5) {
    break;
  }

  console.log(i);
}
for (let i = 0; i < 10; i++) {
  if (i % 2 === 0) {
    continue;
  }

  console.log(i);
}

Functions

Function Declaration

function greet(name) {
  return `Hello, ${name}`;
}

console.log(greet("Alex"));

Function Expression

const greet = function (name) {
  return `Hello, ${name}`;
};

Arrow Function

const add = (a, b) => {
  return a + b;
};
const add = (a, b) => a + b;

Parameters and Arguments

function greet(name = "Guest") {
  return `Hello, ${name}`;
}

greet();
greet("Alex");

Return Values

function square(number) {
  return number * number;
}

const result = square(5);

Higher-Order Functions

function applyOperation(a, b, operation) {
  return operation(a, b);
}

const result = applyOperation(5, 3, (x, y) => x + y);

Callback Functions

function processUser(name, callback) {
  callback(name);
}

processUser("Alex", (name) => {
  console.log(name);
});

Pure Functions

function add(a, b) {
  return a + b;
}

A pure function produces the same output for the same inputs and avoids unwanted side effects.

Scope

Global Scope

const appName = "My App";

function showName() {
  console.log(appName);
}

Function Scope

function test() {
  const message = "Hello";
  console.log(message);
}

Variables declared inside a function are not directly available outside it.

Block Scope

if (true) {
  const message = "Inside block";
  let count = 1;
}

let and const are block-scoped.

Lexical Scope

const outer = "outside";

function parent() {
  const middle = "inside";

  function child() {
    console.log(outer);
    console.log(middle);
  }

  child();
}

Closures

What is a Closure?

A closure occurs when a function retains access to variables from its surrounding lexical scope even after that outer function has finished.

Example

function createCounter() {
  let count = 0;

  return function () {
    count++;
    return count;
  };
}

const counter = createCounter();

console.log(counter());
console.log(counter());
console.log(counter());

Why Closures Matter

Closures are useful for private state, callbacks, factories, event handlers, and functional programming patterns.

Arrays

Creating Arrays

const numbers = [10, 20, 30];
const names = ["Alex", "Sam", "Jordan"];

Accessing Items

const names = ["Alex", "Sam", "Jordan"];

console.log(names[0]);
console.log(names.at(-1));

Adding and Removing

const items = [];

items.push("A");
items.push("B");

items.pop();

items.unshift("Start");
items.shift();

slice

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

const result = numbers.slice(1, 4);

slice() returns a portion of an array without changing the original array.

map

const numbers = [1, 2, 3];

const doubled = numbers.map((number) => {
  return number * 2;
});

filter

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

const even = numbers.filter((number) => {
  return number % 2 === 0;
});

find

const users = [
  { id: 1, name: "Alex" },
  { id: 2, name: "Sam" }
];

const user = users.find((user) => user.id === 2);

some and every

const numbers = [2, 4, 6];

const hasLargeNumber =
  numbers.some((number) => number > 5);

const allEven =
  numbers.every((number) => number % 2 === 0);

reduce

const numbers = [10, 20, 30];

const total = numbers.reduce(
  (sum, number) => sum + number,
  0
);

sort

const numbers = [10, 2, 30, 4];

numbers.sort((a, b) => a - b);

Array Destructuring

const colors = ["red", "green", "blue"];

const [first, second, third] = colors;

Objects

Creating Objects

const user = {
  name: "Alex",
  age: 25,
  active: true
};

Accessing Properties

console.log(user.name);
console.log(user["age"]);

Updating Properties

user.age = 26;
user.active = false;

Adding Properties

user.city = "Delhi";

Methods

const user = {
  name: "Alex",

  greet() {
    return `Hello, ${this.name}`;
  }
};

console.log(user.greet());

Object.keys

Object.keys(user);

Object.values

Object.values(user);

Object.entries

Object.entries(user);

Optional Property Access

const city = user.address?.city;

Destructuring

Object Destructuring

const user = {
  name: "Alex",
  age: 25
};

const { name, age } = user;

Renaming

const { name: userName } = user;

Default Values

const {
  name,
  role = "user"
} = user;

Nested Destructuring

const user = {
  name: "Alex",
  address: {
    city: "Delhi"
  }
};

const {
  address: { city }
} = user;

Array Destructuring

const values = [10, 20, 30];

const [first, second] = values;

Spread & Rest

Spread with Arrays

const first = [1, 2];
const second = [3, 4];

const combined = [...first, ...second];

Spread with Objects

const user = {
  name: "Alex",
  age: 25
};

const updatedUser = {
  ...user,
  age: 26
};

Rest Parameters

function sum(...numbers) {
  return numbers.reduce(
    (total, number) => total + number,
    0
  );
}

console.log(sum(1, 2, 3, 4));

Rest in Destructuring

const [first, ...remaining] = [1, 2, 3, 4];

Strings

Creating Strings

const a = "Hello";
const b = 'Hello';
const c = `Hello`;

Template Literals

const name = "Alex";

const message = `Hello, ${name}!`;

Useful String Methods

const text = "  JavaScript  ";

text.length;
text.trim();
text.toUpperCase();
text.toLowerCase();
text.includes("Script");
text.startsWith("Java");
text.endsWith("Script");
text.slice(0, 4);
text.replace("Java", "Type");

split

const words = "HTML CSS JavaScript".split(" ");

Numbers & Math

Number Methods

Number("42");
Number("3.14");
Number.isNaN(value);
Number.isFinite(value);
Number.isInteger(value);

Math

Math.round(4.6);
Math.floor(4.9);
Math.ceil(4.1);
Math.trunc(4.9);

Math.max(10, 20, 30);
Math.min(10, 20, 30);

Math.random();

Math.sqrt(16);
Math.pow(2, 3);

Floating-Point Numbers

0.1 + 0.2;
// 0.30000000000000004

Floating-point arithmetic follows the representation rules of JavaScript numbers. Avoid assuming that every decimal calculation is exact.

BigInt

const largeNumber = 123456789012345678901234567890n;

Dates

Creating a Date

const now = new Date();

const specificDate =
  new Date("2026-01-01");

Reading Date Parts

const date = new Date();

date.getFullYear();
date.getMonth();
date.getDate();
date.getDay();
date.getHours();
date.getMinutes();
date.getSeconds();

Formatting

const date = new Date();

date.toISOString();
date.toLocaleDateString();
date.toLocaleString();

Internationalization

const date = new Date();

const formatted = new Intl.DateTimeFormat(
  "en-IN",
  {
    dateStyle: "long"
  }
).format(date);

JSON

What is JSON?

JSON is a text format commonly used for exchanging structured data.

{
  "name": "Alex",
  "age": 25,
  "active": true
}

JSON.stringify()

const user = {
  name: "Alex",
  age: 25
};

const json = JSON.stringify(user);

JSON.parse()

const json = '{"name":"Alex","age":25}';

const user = JSON.parse(json);

Errors

Throwing Errors

throw new Error("Something went wrong");

try / catch

try {
  riskyOperation();
} catch (error) {
  console.error(error);
}

finally

try {
  connect();
} catch (error) {
  console.error(error);
} finally {
  cleanup();
}

Custom Errors

class ValidationError extends Error {
  constructor(message) {
    super(message);
    this.name = "ValidationError";
  }
}

DOM

What is the DOM?

The Document Object Model represents the HTML document as a tree of objects that JavaScript can inspect and modify.

Selecting Elements

document.getElementById("title");

document.querySelector(".card");

document.querySelectorAll(".card");

Changing Text

const title = document.querySelector("h1");

title.textContent = "New Title";

Changing HTML

element.innerHTML = "<strong>Hello</strong>";

Use innerHTML carefully when content may come from untrusted sources.

Attributes

const image = document.querySelector("img");

image.setAttribute("alt", "A landscape");

console.log(
  image.getAttribute("alt")
);

Classes

element.classList.add("active");
element.classList.remove("active");
element.classList.toggle("active");
element.classList.contains("active");

Creating Elements

const paragraph =
  document.createElement("p");

paragraph.textContent = "Hello";

document.body.append(paragraph);

Removing Elements

element.remove();

Events

click

const button =
  document.querySelector("button");

button.addEventListener("click", () => {
  console.log("Clicked");
});

Event Object

button.addEventListener("click", (event) => {
  console.log(event.target);
});

Common Events

click
dblclick
input
change
submit
keydown
keyup
focus
blur
mouseover
mouseenter
mouseleave
scroll
load

Prevent Default

form.addEventListener("submit", (event) => {
  event.preventDefault();

  console.log("Form intercepted");
});

Event Bubbling

parent.addEventListener("click", (event) => {
  console.log(event.target);
});

Events often propagate from the target through ancestor elements.

Event Delegation

list.addEventListener("click", (event) => {
  const button = event.target.closest("button");

  if (!button) {
    return;
  }

  console.log(button.dataset.id);
});

Forms

Reading Form Values

const input =
  document.querySelector("#email");

console.log(input.value);

Handling Submit

const form =
  document.querySelector("form");

form.addEventListener("submit", (event) => {
  event.preventDefault();

  const formData = new FormData(form);

  console.log(formData.get("email"));
});

FormData

const formData = new FormData(form);

for (const [name, value] of formData) {
  console.log(name, value);
}

Built-in Validation

if (form.checkValidity()) {
  console.log("Valid");
}

Browser Storage

localStorage

localStorage.setItem(
  "theme",
  "dark"
);

const theme =
  localStorage.getItem("theme");

localStorage.removeItem("theme");

localStorage.clear();

Saving Objects

const settings = {
  theme: "dark",
  fontSize: 18
};

localStorage.setItem(
  "settings",
  JSON.stringify(settings)
);

const savedSettings =
  JSON.parse(
    localStorage.getItem("settings")
  );

sessionStorage

sessionStorage.setItem(
  "step",
  "2"
);

sessionStorage.getItem("step");

Session storage is scoped to the browser session.

Asynchronous JavaScript

Synchronous Code

console.log("A");
console.log("B");
console.log("C");

setTimeout

console.log("Start");

setTimeout(() => {
  console.log("Later");
}, 1000);

console.log("End");

Event Loop Mental Model

Call Stack
    ↓
Web / Runtime APIs
    ↓
Task / Microtask Queues
    ↓
Call Stack

setInterval

const id = setInterval(() => {
  console.log("Running");
}, 1000);

clearInterval(id);

Promises

What is a Promise?

A Promise represents the eventual completion or failure of an asynchronous operation.

Creating a Promise

const promise = new Promise((resolve, reject) => {
  const success = true;

  if (success) {
    resolve("Done");
  } else {
    reject(new Error("Failed"));
  }
});

then and catch

promise
  .then((result) => {
    console.log(result);
  })
  .catch((error) => {
    console.error(error);
  });

finally

promise
  .then(handleSuccess)
  .catch(handleError)
  .finally(() => {
    console.log("Finished");
  });

Promise.all

const results = await Promise.all([
  getUser(),
  getPosts(),
  getSettings()
]);

Promise.allSettled

const results =
  await Promise.allSettled([
    getUser(),
    getPosts()
  ]);

Promise.race

const result =
  await Promise.race([
    request(),
    timeout()
  ]);

Promise.any

const result =
  await Promise.any([
    getFromServerA(),
    getFromServerB()
  ]);

async / await

Basic async Function

async function loadData() {
  return "Data";
}

An async function always returns a Promise.

await

async function loadData() {
  const result = await getData();

  console.log(result);
}

Error Handling

async function loadData() {
  try {
    const result = await getData();
    return result;
  } catch (error) {
    console.error(error);
  }
}

Parallel Operations

async function loadPage() {
  const [user, posts] = await Promise.all([
    getUser(),
    getPosts()
  ]);

  return {
    user,
    posts
  };
}

Fetch API

GET Request

const response =
  await fetch("/api/users");

const data =
  await response.json();

console.log(data);

Checking Response

const response =
  await fetch("/api/users");

if (!response.ok) {
  throw new Error(
    `Request failed: ${response.status}`
  );
}

const data = await response.json();

POST Request

const response = await fetch("/api/users", {
  method: "POST",

  headers: {
    "Content-Type": "application/json"
  },

  body: JSON.stringify({
    name: "Alex",
    age: 25
  })
});

const user = await response.json();

Headers

const response = await fetch("/api/data", {
  headers: {
    Authorization: "Bearer TOKEN"
  }
});

AbortController

const controller = new AbortController();

const response = await fetch("/api/data", {
  signal: controller.signal
});

controller.abort();

Modules

Named Export

// math.js

export function add(a, b) {
  return a + b;
}

export const version = "1.0.0";

Named Import

import {
  add,
  version
} from "./math.js";

Default Export

// user.js

export default class User {
  constructor(name) {
    this.name = name;
  }
}

Default Import

import User from "./user.js";

Module Script in HTML

<script
  type="module"
  src="app.js"
></script>

Classes

Basic Class

class User {
  constructor(name) {
    this.name = name;
  }

  greet() {
    return `Hello, ${this.name}`;
  }
}

const user = new User("Alex");

Class Fields

class Counter {
  count = 0;

  increment() {
    this.count++;
  }
}

Private Fields

class BankAccount {
  #balance = 0;

  deposit(amount) {
    this.#balance += amount;
  }

  getBalance() {
    return this.#balance;
  }
}

Inheritance

class Animal {
  speak() {
    console.log("Animal sound");
  }
}

class Dog extends Animal {
  speak() {
    console.log("Woof");
  }
}

super

class Dog extends Animal {
  constructor(name) {
    super();
    this.name = name;
  }
}

Prototypes

Prototype Chain

Object
  ↓
Prototype
  ↓
Object Instance

JavaScript objects can inherit properties and methods through the prototype chain.

Prototype Method

function User(name) {
  this.name = name;
}

User.prototype.greet = function () {
  return `Hello, ${this.name}`;
};

const user = new User("Alex");

Checking Prototype

Object.getPrototypeOf(user);

this

Object Method

const user = {
  name: "Alex",

  greet() {
    console.log(this.name);
  }
};

user.greet();

Arrow Functions

const user = {
  name: "Alex",

  greet: () => {
    console.log(this.name);
  }
};

Arrow functions do not create their own this binding.

call

function greet() {
  console.log(this.name);
}

greet.call({
  name: "Alex"
});

apply

function add(a, b) {
  return this.value + a + b;
}

add.apply(
  { value: 10 },
  [2, 3]
);

bind

const greet = greetUser.bind({
  name: "Alex"
});

greet();

Map & Set

Map

const users = new Map();

users.set("1", "Alex");
users.set("2", "Sam");

console.log(users.get("1"));
console.log(users.has("2"));
console.log(users.size);

Map Iteration

for (const [id, name] of users) {
  console.log(id, name);
}

Set

const numbers = new Set([
  1,
  2,
  2,
  3
]);

console.log(numbers);

A Set stores unique values.

Set Methods

numbers.add(4);
numbers.delete(2);
numbers.has(3);
numbers.clear();

Iterators & Generators

Iterable Values

const values = [10, 20, 30];

for (const value of values) {
  console.log(value);
}

Iterator

const values = [10, 20, 30];

const iterator = values[Symbol.iterator]();

console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());

Generator

function* numbers() {
  yield 1;
  yield 2;
  yield 3;
}

const generator = numbers();

console.log(generator.next());
console.log(generator.next());
console.log(generator.next());

Regular Expressions

Basic Pattern

const pattern = /hello/;

pattern.test("hello world");

Flags

const pattern = /hello/gi;

Common Patterns

/^[A-Za-z]+$/
/^\d+$/
/^\S+@\S+\.\S+$/

match

const text = "abc 123";

const result =
  text.match(/\d+/);

console.log(result);

replace

const result =
  "hello world".replace(
    /world/,
    "JavaScript"
  );

Functional JavaScript

Functions as Values

const double = (number) => number * 2;

const operation = double;

console.log(operation(5));

map / filter / reduce

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

const result = numbers
  .filter((number) => number % 2 === 0)
  .map((number) => number * 2)
  .reduce((sum, number) => sum + number, 0);

Composition

const double = (x) => x * 2;
const addOne = (x) => x + 1;

const result =
  addOne(double(5));

Immutability

const user = {
  name: "Alex",
  age: 25
};

const updatedUser = {
  ...user,
  age: 26
};

Modern JavaScript

Template Literals

const name = "Alex";

const message = `Hello, ${name}`;

Optional Chaining

const city = user?.address?.city;

Nullish Coalescing

const name =
  userName ?? "Guest";

Logical Assignment

value ||= fallback;

value &&= updatedValue;

value ??= defaultValue;

Private Class Fields

class Counter {
  #count = 0;

  increment() {
    this.#count++;
  }
}

Dynamic Import

const module =
  await import("./feature.js");

Top-Level await

// module.js

const response =
  await fetch("/api/data");

const data =
  await response.json();

Performance

Avoid Unnecessary DOM Work

const fragment =
  document.createDocumentFragment();

for (const item of items) {
  const element =
    document.createElement("li");

  element.textContent = item;
  fragment.append(element);
}

list.append(fragment);

Debouncing

function debounce(callback, delay) {
  let timer;

  return (...args) => {
    clearTimeout(timer);

    timer = setTimeout(() => {
      callback(...args);
    }, delay);
  };
}

Throttling

function throttle(callback, delay) {
  let waiting = false;

  return (...args) => {
    if (waiting) {
      return;
    }

    callback(...args);

    waiting = true;

    setTimeout(() => {
      waiting = false;
    }, delay);
  };
}

Lazy Loading Modules

button.addEventListener("click", async () => {
  const module =
    await import("./heavy-feature.js");

  module.start();
});

Common Mistakes

Using var for Everything

var name = "Alex";

Prefer const by default and let when reassignment is required.

Using == Without Understanding Coercion

5 == "5";

Prefer strict equality when you want predictable type-sensitive comparisons.

Mutating Data Unintentionally

const user = {
  name: "Alex"
};

const updated = {
  ...user,
  name: "Sam"
};

Ignoring Async Errors

try {
  const data = await fetchData();
} catch (error) {
  console.error(error);
}

Forgetting await

const data = fetchData();

console.log(data);

An asynchronous function commonly returns a Promise, not the final value.

const data = await fetchData();

Unnecessary Global State

Keep state as close as possible to the code that owns it. Excessive global state makes applications harder to reason about and test.

Ignoring Event Cleanup

function handleResize() {
  console.log(window.innerWidth);
}

window.addEventListener(
  "resize",
  handleResize
);

window.removeEventListener(
  "resize",
  handleResize
);

Real Project Example

HTML

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">

  <meta
    name="viewport"
    content="width=device-width, initial-scale=1.0"
  >

  <title>Task App</title>

  <link rel="stylesheet" href="coding.css">
</head>

<body>

  <main>

    <h1>Tasks</h1>

    <form id="task-form">
      <input
        id="task-input"
        name="task"
        type="text"
        required
      >

      <button type="submit">
        Add Task
      </button>
    </form>

    <ul id="task-list"></ul>

  </main>

  <script
    type="module"
    src="app.js"
  ></script>

</body>

</html>

JavaScript

const form =
  document.querySelector("#task-form");

const input =
  document.querySelector("#task-input");

const list =
  document.querySelector("#task-list");

const tasks = [];

function renderTasks() {
  list.innerHTML = "";

  for (const [index, task] of tasks.entries()) {
    const item =
      document.createElement("li");

    item.innerHTML = `
      <span>${task}</span>
      <button
        type="button"
        data-index="${index}"
      >
        Delete
      </button>
    `;

    list.append(item);
  }
}

form.addEventListener("submit", (event) => {
  event.preventDefault();

  const task =
    input.value.trim();

  if (!task) {
    return;
  }

  tasks.push(task);

  input.value = "";

  renderTasks();
});

list.addEventListener("click", (event) => {
  const button =
    event.target.closest(
      "button[data-index]"
    );

  if (!button) {
    return;
  }

  const index =
    Number(button.dataset.index);

  tasks.splice(index, 1);

  renderTasks();
});

renderTasks();

Better Rendering Pattern

function createTaskElement(task, index) {
  const item =
    document.createElement("li");

  const text =
    document.createElement("span");

  const button =
    document.createElement("button");

  text.textContent = task;

  button.type = "button";
  button.dataset.index = index;
  button.textContent = "Delete";

  item.append(text, button);

  return item;
}

Creating DOM nodes with textContent avoids treating task text as HTML.

JavaScript Cheat Sheet

Variables

const name = "Alex";
let count = 0;

Functions

function add(a, b) {
  return a + b;
}

const multiply = (a, b) => a * b;

Conditionals

if (condition) {
  ...
} else {
  ...
}

const result =
  condition
    ? valueA
    : valueB;

Loops

for (const item of items) {
  ...
}

for (const key in object) {
  ...
}

Arrays

items.map(...)
items.filter(...)
items.find(...)
items.some(...)
items.every(...)
items.reduce(...)
items.forEach(...)

Objects

const user = {
  name: "Alex",
  age: 25
};

user.name;
user["age"];

Object.keys(user);
Object.values(user);
Object.entries(user);

Destructuring

const { name, age } = user;

const [first, second] = items;

Spread and Rest

const copy = {
  ...user
};

const combined = [
  ...first,
  ...second
];

function sum(...numbers) {
  ...
}

DOM

document.querySelector("...");
document.querySelectorAll("...");

element.textContent = "...";

element.classList.add("active");

element.addEventListener("click", handler);

document.createElement("div");

Async

async function load() {
  const data = await fetchData();
  return data;
}

try {
  const data = await load();
} catch (error) {
  console.error(error);
}

Fetch

const response =
  await fetch("/api/data");

if (!response.ok) {
  throw new Error("Request failed");
}

const data =
  await response.json();

Modules

export function add(a, b) {
  return a + b;
}

import { add } from "./math.js";

Error Handling

try {
  riskyOperation();
} catch (error) {
  console.error(error);
} finally {
  cleanup();
}

Learning Path

1. Learn the Fundamentals

Master variables, data types, operators, expressions, conditionals, loops, and basic functions.

2. Master Functions

Learn declarations, expressions, arrow functions, callbacks, higher-order functions, scope, and closures.

3. Master Data Structures

Practice arrays, objects, destructuring, spread, rest, Map, Set, and JSON.

4. Understand the Language

Study coercion, equality, prototypes, this, closures, iterators, generators, and the event loop.

5. Learn the Browser

Master the DOM, events, forms, browser storage, and browser APIs.

6. Learn Asynchronous JavaScript

Understand callbacks, Promises, async, await, fetch, concurrency, and error handling.

7. Learn Modules

Understand exports, imports, module boundaries, and dynamic imports.

8. Learn Object-Oriented JavaScript

Practice classes, inheritance, private fields, prototypes, and object composition.

9. Learn Modern JavaScript

Add optional chaining, nullish coalescing, logical assignment, modern collection APIs, and other language features to your toolkit.

10. Build Projects

Build real applications such as task managers, search interfaces, dashboards, API clients, forms, games, and interactive websites.

JavaScript Mastery Summary

The Core Mental Model

Values
  ↓
Variables
  ↓
Expressions
  ↓
Functions
  ↓
State
  ↓
Events / Async Work
  ↓
Output

Browser Mental Model

HTML
  ↓
DOM
  ↓
JavaScript
  ↓
Events
  ↓
State Changes
  ↓
DOM Updates

Async Mental Model

Start operation
      ↓
Promise
      ↓
Await / then
      ↓
Success or Error
      ↓
Update application state
      ↓
Update UI

Essential JavaScript Workflow

1. Understand the input
2. Store state in variables or data structures
3. Write small reusable functions
4. Validate conditions
5. Transform data
6. Handle errors
7. Handle asynchronous work
8. Update the DOM when necessary
9. Keep modules focused
10. Test behavior and edge cases

What to Remember

  • Prefer const and use let when reassignment is necessary.
  • Understand values, references, scope, and closures.
  • Use functions to isolate logic.
  • Use array methods intentionally rather than blindly chaining them.
  • Understand how this works before using it in complex code.
  • Handle asynchronous operations with Promises and async/await.
  • Check network responses and handle failures.
  • Prefer semantic DOM operations and safe text insertion.
  • Use modules to keep larger applications organized.
  • Build projects to turn language knowledge into practical skill.