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
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";
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.
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;
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];
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);
});
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()
]);
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();
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();
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
};
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.