JavaScript is the language of the web — the only programming language that runs natively in every browser, and now on servers too. This tutorial takes you from zero to writing real JavaScript programs, with no prior experience required.
What you'll learn
| Topic | What you'll be able to do |
|---|---|
| Setup | Run JavaScript in the browser and Node.js |
| Syntax & variables | Understand how JS code works |
| Data types | Work with strings, numbers, arrays, objects |
| Control flow | Use if/else, loops, and conditions |
| Functions | Write reusable, clean code |
| DOM | Make web pages interactive |
| Async JS | Fetch data from APIs |
| ES6+ | Use modern JavaScript features |
| Projects | Build 3 real programs |
JavaScript version: ES2024 (modern JS, works in all current browsers)
Part 1 — Why JavaScript?
| Use case | What you can build |
|---|---|
| Frontend | Interactive websites and web apps |
| Backend | Servers with Node.js |
| Mobile | iOS/Android apps with React Native |
| Desktop | Apps with Electron (VS Code, Slack) |
| CLI tools | Command-line scripts |
| Browser extensions | Chrome, Firefox add-ons |
| Game development | Browser-based games with Canvas/WebGL |
JavaScript is the only language that runs everywhere: browsers, servers, phones, and desktops. Learning JS opens more doors than almost any other language.
Should you learn JavaScript or Python first?
- JavaScript — if you want to build websites, web apps, or anything visual
- Python — if you want to do data science, AI/ML, or scripting
Both are excellent first languages.
Part 2 — Setup
Option 1: Browser console (zero setup)
Open any browser (Chrome, Firefox, Edge) and press:
- Windows/Linux:
Ctrl + Shift + J - macOS:
Cmd + Option + J
You now have a JavaScript REPL. Type:
console.log("Hello, JavaScript!");
Option 2: HTML file
Create a file index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My JS Project</title>
</head>
<body>
<h1>Hello!</h1>
<script src="script.js"></script>
</body>
</html>
Create script.js:
console.log("Hello from script.js!");
Open index.html in your browser and check the console.
Option 3: Node.js (run JS outside the browser)
- Download Node.js from nodejs.org (LTS version)
- Install it
- Create
hello.js:
console.log("Hello, Node.js!");
- Run it:
node hello.js
Recommended editor
VS Code (free, by Microsoft) with the extensions:
- ESLint — catches errors
- Prettier — auto-formats code
Part 3 — JavaScript Syntax Basics
Comments
// Single-line comment
/*
Multi-line
comment
*/
Semicolons
Semicolons are optional in JavaScript (ASI inserts them automatically), but many developers use them for clarity:
console.log("With semicolon");
console.log("Without semicolon") // also valid
Convention: Choose one style and be consistent. Most modern code omits semicolons with Prettier handling formatting.
Your first program
let name = "Alice";
let age = 25;
console.log("Name:", name);
console.log("Age:", age);
console.log(`Hello, ${name}! You are ${age} years old.`);
Part 4 — Variables
JavaScript has three ways to declare variables:
| Keyword | Scope | Reassignable | Redeclarable | Use when |
|---|---|---|---|---|
var |
function | yes | yes | ❌ avoid (legacy) |
let |
block | yes | no | value changes |
const |
block | no* | no | value doesn't change |
*const objects/arrays can still be mutated — only the binding is constant.
// const — use by default
const PI = 3.14159;
const name = "Alice";
// let — when value changes
let score = 0;
score = 10; // ok
// var — don't use in modern code
var old = "legacy"; // function-scoped, confusing
Rule of thumb: Use const by default. Use let when you need to reassign. Never use var.
Part 5 — Data Types
JavaScript has 8 data types:
| Type | Example | Description |
|---|---|---|
number |
42, 3.14, -7 |
All numbers (no int/float split) |
string |
"hello", 'world', `hi` |
Text |
boolean |
true, false |
True/false |
null |
null |
Intentional empty value |
undefined |
undefined |
Variable declared but not assigned |
object |
{}, [] |
Key-value pairs; arrays are objects |
symbol |
Symbol("id") |
Unique identifiers (advanced) |
bigint |
9007199254740991n |
Very large integers |
// Check type with typeof
console.log(typeof 42); // "number"
console.log(typeof "hello"); // "string"
console.log(typeof true); // "boolean"
console.log(typeof null); // "object" (historic bug in JS!)
console.log(typeof undefined); // "undefined"
console.log(typeof {}); // "object"
console.log(typeof []); // "object" (arrays are objects)
console.log(typeof function(){}); // "function"
Strings
const single = 'single quotes';
const double = "double quotes";
const template = `template literal`; // backtick — preferred
const name = "Alice";
const age = 25;
// String concatenation (old way)
console.log("Hello, " + name + "!");
// Template literals (modern, preferred)
console.log(`Hello, ${name}! You are ${age} years old.`);
console.log(`2 + 2 = ${2 + 2}`); // expressions work too
// String methods
const str = "Hello, World!";
console.log(str.length); // 13
console.log(str.toUpperCase()); // "HELLO, WORLD!"
console.log(str.toLowerCase()); // "hello, world!"
console.log(str.includes("World")); // true
console.log(str.startsWith("Hello")); // true
console.log(str.slice(0, 5)); // "Hello"
console.log(str.replace("World", "JS")); // "Hello, JS!"
console.log(" hello ".trim()); // "hello"
console.log("a,b,c".split(",")); // ["a", "b", "c"]
Numbers
const int = 42;
const float = 3.14;
const negative = -7;
// Arithmetic
console.log(10 + 3); // 13
console.log(10 - 3); // 7
console.log(10 * 3); // 30
console.log(10 / 3); // 3.3333...
console.log(10 % 3); // 1 (remainder)
console.log(10 ** 3); // 1000 (exponentiation)
// Math object
console.log(Math.round(4.6)); // 5
console.log(Math.floor(4.9)); // 4
console.log(Math.ceil(4.1)); // 5
console.log(Math.abs(-5)); // 5
console.log(Math.max(1, 2, 3)); // 3
console.log(Math.min(1, 2, 3)); // 1
console.log(Math.random()); // random number 0–1
console.log(Math.sqrt(16)); // 4
// parseInt / parseFloat
console.log(parseInt("42px")); // 42
console.log(parseFloat("3.14")); // 3.14
console.log(Number("42")); // 42
console.log(Number("abc")); // NaN (Not a Number)
console.log(isNaN(NaN)); // true
Booleans
const isLoggedIn = true;
const hasPermission = false;
// Truthy vs falsy values
// Falsy: false, 0, "", null, undefined, NaN
// Truthy: everything else
if (0) console.log("falsy"); // won't run
if ("hello") console.log("truthy"); // will run
if ([]) console.log("truthy"); // will run (empty array!)
if ({}) console.log("truthy"); // will run (empty object!)
null vs undefined
let a; // undefined — declared, no value
let b = null; // null — intentionally empty
console.log(a === undefined); // true
console.log(b === null); // true
// Nullish coalescing — use default when null/undefined
const username = null;
const display = username ?? "Guest"; // "Guest"
Part 6 — Arrays
Arrays store ordered lists of values.
// Create an array
const fruits = ["apple", "banana", "cherry"];
const mixed = [1, "two", true, null, { name: "Bob" }];
// Access elements (0-indexed)
console.log(fruits[0]); // "apple"
console.log(fruits[2]); // "cherry"
console.log(fruits.length); // 3
// Modify elements
fruits[0] = "mango";
console.log(fruits); // ["mango", "banana", "cherry"]
// Add/remove elements
fruits.push("grape"); // add to end
fruits.pop(); // remove from end
fruits.unshift("kiwi"); // add to start
fruits.shift(); // remove from start
// Useful array methods
const numbers = [3, 1, 4, 1, 5, 9, 2, 6];
// map — transform each element
const doubled = numbers.map(n => n * 2);
console.log(doubled); // [6, 2, 8, 2, 10, 18, 4, 12]
// filter — keep matching elements
const bigNumbers = numbers.filter(n => n > 4);
console.log(bigNumbers); // [5, 9, 6]
// find — first matching element
const firstBig = numbers.find(n => n > 4);
console.log(firstBig); // 5
// reduce — combine into single value
const sum = numbers.reduce((acc, n) => acc + n, 0);
console.log(sum); // 31
// sort
const sorted = [...numbers].sort((a, b) => a - b);
console.log(sorted); // [1, 1, 2, 3, 4, 5, 6, 9]
// includes / indexOf
console.log(numbers.includes(5)); // true
console.log(numbers.indexOf(4)); // 2
// slice (non-destructive)
console.log(numbers.slice(1, 4)); // [1, 4, 1]
// splice (destructive — modifies original)
const arr = [1, 2, 3, 4, 5];
arr.splice(2, 1); // remove 1 element at index 2
console.log(arr); // [1, 2, 4, 5]
// Spread operator
const a = [1, 2, 3];
const b = [4, 5, 6];
const combined = [...a, ...b]; // [1, 2, 3, 4, 5, 6]
// Destructuring
const [first, second, ...rest] = [1, 2, 3, 4, 5];
console.log(first); // 1
console.log(second); // 2
console.log(rest); // [3, 4, 5]
Part 7 — Objects
Objects store key-value pairs.
// Create an object
const person = {
name: "Alice",
age: 25,
isStudent: true,
hobbies: ["reading", "coding"],
address: {
city: "New York",
country: "USA"
}
};
// Access properties
console.log(person.name); // "Alice" (dot notation)
console.log(person["age"]); // 25 (bracket notation)
console.log(person.address.city); // "New York" (nested)
// Add/update/delete properties
person.email = "alice@example.com"; // add
person.age = 26; // update
delete person.isStudent; // delete
// Check if property exists
console.log("name" in person); // true
console.log(person.hasOwnProperty("name")); // true
// Iterate over object
for (const key in person) {
console.log(`${key}: ${person[key]}`);
}
Object.keys(person); // array of keys
Object.values(person); // array of values
Object.entries(person); // array of [key, value] pairs
// Destructuring
const { name, age, address: { city } } = person;
console.log(name); // "Alice"
console.log(city); // "New York"
// Spread operator
const updated = { ...person, age: 27 }; // copy with update
// Shorthand property names
const x = 10;
const y = 20;
const point = { x, y }; // same as { x: x, y: y }
// Computed property names
const key = "dynamicKey";
const obj = { [key]: "value" }; // { dynamicKey: "value" }
Part 8 — Control Flow
if / else
const score = 85;
if (score >= 90) {
console.log("A");
} else if (score >= 80) {
console.log("B");
} else if (score >= 70) {
console.log("C");
} else {
console.log("F");
}
// Ternary operator (one-liner if/else)
const grade = score >= 60 ? "Pass" : "Fail";
// Nullish coalescing — default for null/undefined
const username = null;
const display = username ?? "Guest";
// Optional chaining — safe property access
const user = { profile: { name: "Alice" } };
console.log(user?.profile?.name); // "Alice"
console.log(user?.settings?.theme); // undefined (no error)
switch
const day = "Monday";
switch (day) {
case "Monday":
case "Tuesday":
case "Wednesday":
case "Thursday":
case "Friday":
console.log("Weekday");
break;
case "Saturday":
case "Sunday":
console.log("Weekend");
break;
default:
console.log("Unknown day");
}
Comparison operators
// == vs === (always use ===)
console.log(1 == "1"); // true (type coercion — confusing!)
console.log(1 === "1"); // false (strict equality — correct)
console.log(1 !== "1"); // true
// Logical operators
console.log(true && false); // false (AND)
console.log(true || false); // true (OR)
console.log(!true); // false (NOT)
for loop
// Classic for loop
for (let i = 0; i < 5; i++) {
console.log(i); // 0, 1, 2, 3, 4
}
// for...of (iterate over arrays/strings)
const fruits = ["apple", "banana", "cherry"];
for (const fruit of fruits) {
console.log(fruit);
}
// for...in (iterate over object keys)
const person = { name: "Alice", age: 25 };
for (const key in person) {
console.log(`${key}: ${person[key]}`);
}
// forEach
fruits.forEach((fruit, index) => {
console.log(`${index}: ${fruit}`);
});
while loop
let count = 0;
while (count < 5) {
console.log(count);
count++;
}
// do...while (runs at least once)
let n = 0;
do {
console.log(n);
n++;
} while (n < 5);
// break and continue
for (let i = 0; i < 10; i++) {
if (i === 3) continue; // skip 3
if (i === 7) break; // stop at 7
console.log(i); // 0, 1, 2, 4, 5, 6
}
Part 9 — Functions
// Function declaration
function greet(name) {
return `Hello, ${name}!`;
}
console.log(greet("Alice")); // "Hello, Alice!"
// Function expression
const add = function(a, b) {
return a + b;
};
// Arrow function (modern, preferred for most cases)
const multiply = (a, b) => a * b;
const square = n => n * n; // single param — no parens needed
const getPI = () => 3.14; // no params
// Default parameters
function greetUser(name = "Guest") {
return `Hello, ${name}!`;
}
console.log(greetUser()); // "Hello, Guest!"
console.log(greetUser("Alice")); // "Hello, Alice!"
// Rest parameters
function sum(...numbers) {
return numbers.reduce((acc, n) => acc + n, 0);
}
console.log(sum(1, 2, 3, 4, 5)); // 15
// Spread when calling
const nums = [1, 2, 3];
console.log(Math.max(...nums)); // 3
Scope
const globalVar = "I'm global";
function outer() {
const outerVar = "I'm in outer";
function inner() {
const innerVar = "I'm in inner";
console.log(globalVar); // accessible
console.log(outerVar); // accessible (closure)
console.log(innerVar); // accessible
}
inner();
// console.log(innerVar); // Error — not accessible here
}
Closures
A closure is a function that remembers the variables from its surrounding scope:
function makeCounter() {
let count = 0;
return {
increment() { count++; },
decrement() { count--; },
value() { return count; }
};
}
const counter = makeCounter();
counter.increment();
counter.increment();
counter.increment();
counter.decrement();
console.log(counter.value()); // 2
Higher-order functions
Functions that take or return other functions:
// Takes a function as argument
function applyTwice(fn, value) {
return fn(fn(value));
}
const double = x => x * 2;
console.log(applyTwice(double, 3)); // 12
// Returns a function
function multiplier(factor) {
return n => n * factor;
}
const triple = multiplier(3);
console.log(triple(5)); // 15
Part 10 — DOM Manipulation
The Document Object Model (DOM) lets JavaScript interact with HTML.
<!-- HTML -->
<button id="myBtn">Click me</button>
<p id="output">Hello</p>
<ul id="list"></ul>
// Select elements
const btn = document.getElementById("myBtn");
const output = document.querySelector("#output"); // CSS selector
const all = document.querySelectorAll("p"); // all <p> elements
// Read/write content
console.log(output.textContent); // "Hello"
output.textContent = "World"; // change text
output.innerHTML = "<strong>Bold</strong>"; // HTML content
// Change styles
output.style.color = "red";
output.style.fontSize = "24px";
// Classes
output.classList.add("highlight");
output.classList.remove("highlight");
output.classList.toggle("active");
output.classList.contains("active"); // true/false
// Attributes
const link = document.querySelector("a");
link.getAttribute("href");
link.setAttribute("href", "https://example.com");
// Create and add elements
const li = document.createElement("li");
li.textContent = "New item";
document.getElementById("list").appendChild(li);
// Events
btn.addEventListener("click", function() {
output.textContent = "Button clicked!";
});
btn.addEventListener("click", (event) => {
console.log(event.target); // the button element
event.preventDefault(); // prevent default action (forms, links)
});
// Common events
// click, dblclick, mouseover, mouseout, mouseenter, mouseleave
// keydown, keyup, keypress
// input, change, submit, focus, blur
// load, DOMContentLoaded, resize, scroll
Form handling
const form = document.querySelector("form");
const input = document.querySelector("#username");
form.addEventListener("submit", (event) => {
event.preventDefault(); // prevent page reload
const value = input.value.trim();
if (value === "") {
console.log("Username required");
return;
}
console.log("Submitted:", value);
});
input.addEventListener("input", (event) => {
console.log("Typing:", event.target.value);
});
Part 11 — Async JavaScript
JavaScript is single-threaded. Async programming lets it handle slow operations (network, file I/O) without blocking.
Callbacks (old way)
// Problem: callback hell
setTimeout(() => {
console.log("Step 1");
setTimeout(() => {
console.log("Step 2");
setTimeout(() => {
console.log("Step 3");
}, 1000);
}, 1000);
}, 1000);
Promises (modern)
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// Promise chain
delay(1000)
.then(() => {
console.log("Step 1");
return delay(1000);
})
.then(() => {
console.log("Step 2");
return delay(1000);
})
.then(() => {
console.log("Step 3");
})
.catch(error => {
console.error("Error:", error);
});
// Promise.all — wait for multiple promises
const p1 = fetch("https://api.example.com/users");
const p2 = fetch("https://api.example.com/posts");
Promise.all([p1, p2])
.then(([users, posts]) => console.log("Both done"))
.catch(err => console.error(err));
async/await (cleanest)
async function fetchUser(id) {
try {
const response = await fetch(`https://jsonplaceholder.typicode.com/users/${id}`);
if (!response.ok) {
throw new Error(`HTTP error: ${response.status}`);
}
const user = await response.json();
return user;
} catch (error) {
console.error("Failed to fetch user:", error.message);
throw error;
}
}
// Call async function
async function main() {
const user = await fetchUser(1);
console.log(user.name); // "Leanne Graham"
}
main();
// Parallel async operations
async function getMultiple() {
const [user, posts] = await Promise.all([
fetch("https://jsonplaceholder.typicode.com/users/1").then(r => r.json()),
fetch("https://jsonplaceholder.typicode.com/posts?userId=1").then(r => r.json())
]);
console.log(user, posts);
}
Part 12 — Modern JavaScript (ES6+)
These features are used everywhere in modern JS code:
Destructuring
// Array destructuring
const [a, b, ...rest] = [1, 2, 3, 4, 5];
// Object destructuring
const { name, age, city = "Unknown" } = person;
// Function parameter destructuring
function displayUser({ name, age }) {
console.log(`${name} is ${age}`);
}
displayUser({ name: "Alice", age: 25 });
Spread and rest
// Spread — expand iterable
const arr1 = [1, 2, 3];
const arr2 = [...arr1, 4, 5];
const obj1 = { a: 1 };
const obj2 = { ...obj1, b: 2 };
// Rest — collect remaining
function first(a, b, ...rest) {
console.log(a, b, rest); // 1, 2, [3, 4, 5]
}
first(1, 2, 3, 4, 5);
Modules (ES modules)
// math.js — export
export function add(a, b) { return a + b; }
export function subtract(a, b) { return a - b; }
export const PI = 3.14159;
export default class Calculator { /* ... */ }
// main.js — import
import Calculator, { add, subtract, PI } from "./math.js";
import * as math from "./math.js"; // import all as namespace
console.log(add(2, 3)); // 5
Classes
class Animal {
#name; // private field
constructor(name, sound) {
this.#name = name;
this.sound = sound;
}
speak() {
console.log(`${this.#name} says ${this.sound}`);
}
get name() { return this.#name; }
}
class Dog extends Animal {
constructor(name) {
super(name, "Woof");
this.tricks = [];
}
learn(trick) {
this.tricks.push(trick);
}
speak() {
super.speak();
console.log(`${this.name} knows: ${this.tricks.join(", ")}`);
}
}
const dog = new Dog("Rex");
dog.learn("sit");
dog.learn("shake");
dog.speak();
// Rex says Woof
// Rex knows: sit, shake
Optional chaining and nullish coalescing
const user = {
profile: {
address: null
}
};
// Optional chaining — no error if property doesn't exist
const city = user?.profile?.address?.city; // undefined (not an error)
const method = user?.someMethod?.(); // safe method call
// Nullish coalescing — default for null/undefined
const displayCity = city ?? "No city"; // "No city"
// Logical assignment
user.name ??= "Guest"; // assign if null/undefined
user.count ||= 0; // assign if falsy
user.count &&= user.count + 1; // assign if truthy
Part 13 — Error Handling
// try/catch/finally
function divide(a, b) {
if (b === 0) throw new Error("Cannot divide by zero");
return a / b;
}
try {
const result = divide(10, 0);
console.log(result);
} catch (error) {
console.error("Error:", error.message);
} finally {
console.log("Always runs");
}
// Custom error types
class ValidationError extends Error {
constructor(message, field) {
super(message);
this.name = "ValidationError";
this.field = field;
}
}
function validateEmail(email) {
if (!email.includes("@")) {
throw new ValidationError("Invalid email", "email");
}
}
try {
validateEmail("not-an-email");
} catch (error) {
if (error instanceof ValidationError) {
console.log(`Validation failed on field: ${error.field}`);
} else {
throw error; // re-throw unexpected errors
}
}
Part 14 — Three Projects
Project 1: Interactive To-Do List
<!-- index.html -->
<div id="app">
<h1>To-Do List</h1>
<div>
<input id="taskInput" type="text" placeholder="Add a task...">
<button id="addBtn">Add</button>
</div>
<ul id="taskList"></ul>
<p id="counter">0 tasks</p>
</div>
<script src="todo.js"></script>
// todo.js
const tasks = [];
const taskInput = document.getElementById("taskInput");
const addBtn = document.getElementById("addBtn");
const taskList = document.getElementById("taskList");
const counter = document.getElementById("counter");
function renderTasks() {
taskList.innerHTML = "";
tasks.forEach((task, index) => {
const li = document.createElement("li");
li.style.textDecoration = task.done ? "line-through" : "none";
const checkbox = document.createElement("input");
checkbox.type = "checkbox";
checkbox.checked = task.done;
checkbox.addEventListener("change", () => toggleTask(index));
const span = document.createElement("span");
span.textContent = task.text;
const deleteBtn = document.createElement("button");
deleteBtn.textContent = "Delete";
deleteBtn.addEventListener("click", () => deleteTask(index));
li.append(checkbox, span, deleteBtn);
taskList.appendChild(li);
});
counter.textContent = `${tasks.filter(t => !t.done).length} tasks remaining`;
}
function addTask() {
const text = taskInput.value.trim();
if (!text) return;
tasks.push({ text, done: false });
taskInput.value = "";
renderTasks();
}
function toggleTask(index) {
tasks[index].done = !tasks[index].done;
renderTasks();
}
function deleteTask(index) {
tasks.splice(index, 1);
renderTasks();
}
addBtn.addEventListener("click", addTask);
taskInput.addEventListener("keypress", (e) => {
if (e.key === "Enter") addTask();
});
renderTasks();
Project 2: Weather App (using an API)
<!-- index.html -->
<h1>Weather App</h1>
<div>
<input id="cityInput" type="text" placeholder="Enter city...">
<button id="searchBtn">Search</button>
</div>
<div id="result"></div>
<script src="weather.js"></script>
// weather.js
// Uses Open-Meteo (free, no API key needed)
const cityInput = document.getElementById("cityInput");
const searchBtn = document.getElementById("searchBtn");
const result = document.getElementById("result");
async function getCoordinates(city) {
const url = `https://geocoding-api.open-meteo.com/v1/search?name=${encodeURIComponent(city)}&count=1`;
const response = await fetch(url);
const data = await response.json();
if (!data.results?.length) throw new Error("City not found");
return data.results[0];
}
async function getWeather(lat, lon) {
const url = `https://api.open-meteo.com/v1/forecast?latitude=${lat}&longitude=${lon}¤t_weather=true`;
const response = await fetch(url);
return response.json();
}
async function searchWeather() {
const city = cityInput.value.trim();
if (!city) return;
result.textContent = "Loading...";
try {
const location = await getCoordinates(city);
const weather = await getWeather(location.latitude, location.longitude);
const temp = weather.current_weather.temperature;
const wind = weather.current_weather.windspeed;
result.innerHTML = `
<h2>${location.name}, ${location.country_code}</h2>
<p>🌡️ Temperature: ${temp}°C</p>
<p>💨 Wind speed: ${wind} km/h</p>
`;
} catch (error) {
result.textContent = `Error: ${error.message}`;
}
}
searchBtn.addEventListener("click", searchWeather);
cityInput.addEventListener("keypress", (e) => {
if (e.key === "Enter") searchWeather();
});
Project 3: Number Guessing Game
// game.js
function createGame(min = 1, max = 100) {
const secret = Math.floor(Math.random() * (max - min + 1)) + min;
let attempts = 0;
const maxAttempts = 10;
return {
guess(n) {
attempts++;
const num = Number(n);
if (isNaN(num) || num < min || num > max) {
return { valid: false, message: `Enter a number between ${min} and ${max}` };
}
if (num === secret) {
return { valid: true, won: true, attempts, message: `🎉 Correct! You got it in ${attempts} attempt(s)!` };
}
if (attempts >= maxAttempts) {
return { valid: true, won: false, message: `Game over! The number was ${secret}.` };
}
const hint = num < secret ? "Too low" : "Too high";
return { valid: true, won: false, message: `${hint}! Attempts: ${attempts}/${maxAttempts}` };
},
remaining: () => maxAttempts - attempts
};
}
// Play in the console
const game = createGame();
console.log("Guess a number between 1 and 100!");
// Example: game.guess(50) → { valid: true, won: false, message: "Too low! Attempts: 1/10" }
// game.guess(75) → ...
JavaScript Learning Path
| Stage | Topics | Time |
|---|---|---|
| Beginner | Variables, data types, control flow, functions | 2–4 weeks |
| Intermediate | DOM, events, async/await, fetch API | 2–4 weeks |
| Advanced beginner | ES6+ (classes, modules, destructuring) | 2–4 weeks |
| Framework ready | React or Vue basics | 4–8 weeks |
| Job ready | TypeScript, testing, Git, real projects | 3–6 months |
JavaScript vs other languages
| Feature | JavaScript | Python | Java |
|---|---|---|---|
| Where it runs | Browser + Node.js | Everywhere | JVM |
| Main use | Web + fullstack | Data/AI/scripting | Enterprise/Android |
| Typing | Dynamic | Dynamic | Static |
| Learning curve | Medium (async tricky) | Gentle | Steep |
| Performance | Fast (V8 JIT) | Slower | Fast |
| Jobs | Most in-demand | Very high | High |
| Syntax | C-like | Whitespace | Verbose |
Common mistakes
| Mistake | Problem | Fix |
|---|---|---|
Using == instead of === |
Type coercion surprises | Always use === |
var instead of let/const |
Confusing scope | Use const by default |
| Not handling async errors | Silent failures | Always use try/catch with async/await |
| Mutating arrays/objects directly | Unexpected side effects | Use spread/map/filter |
typeof null === "object" |
Historic JS bug | Use value === null to check for null |
Forgetting await |
Gets a Promise, not the value | Always await async functions |
| Arrow functions for methods | Wrong this binding |
Use regular functions for object methods |
forEach with async |
Doesn't work as expected | Use for...of for async loops |
JavaScript vs related terms
| Term | What it is |
|---|---|
| JavaScript | The language itself |
| TypeScript | JS with static types (compiles to JS) |
| Node.js | JS runtime outside the browser |
| npm | Package manager for JS |
| React | UI library built with JS |
| Next.js | React framework with SSR/SSG |
| Deno | Alternative to Node.js |
| Bun | Fast JS runtime + package manager |
| ECMAScript | Official spec for JavaScript (ES6 = ES2015) |
| V8 | Google's JS engine (used in Chrome/Node.js) |
Frequently asked questions
Do I need to learn HTML and CSS before JavaScript? Basic HTML is helpful (you need it to manipulate the DOM), but you can start JavaScript in the browser console or Node.js with zero HTML knowledge. Learn HTML basics alongside JavaScript.
How long does it take to learn JavaScript? Basic syntax: 1–2 weeks. DOM and async programming: 1–2 months. Job-ready with a framework: 6–12 months. It depends entirely on how much you practice by building real projects.
JavaScript or TypeScript? Learn JavaScript first — TypeScript adds types on top of JS, so you need to understand JS first. Most developers switch to TypeScript after 3–6 months of JavaScript experience.
What framework should I learn after JavaScript? React is the most in-demand (by far). Vue is easier to learn. Angular is common in enterprise. For server-side, start with plain Node.js/Express, then consider NestJS.
Why is JavaScript asynchronous? Because it's single-threaded — it can only do one thing at a time. Async programming lets slow operations (network requests, timers) run "in the background" via the event loop, so the main thread stays responsive.
Can I get a job with just JavaScript (no frameworks)? Unlikely for a frontend role — employers almost always want React, Vue, or Angular. However, understanding core JavaScript deeply makes you much better at any framework. Don't skip the fundamentals.