HTML gives a page its structure. CSS gives it its appearance. Neither one can respond to anything you do. A button built with HTML and CSS alone will sit there looking clickable and do absolutely nothing when you press it.
JavaScript is the third layer — the one that makes a page do things. It is the language behind the dropdown menu that opens, the form that tells you a field is empty, the search box that updates results as you type, and the entire single-page application that never reloads.
This guide covers what JavaScript is, how it runs, and the core ideas you need before you can build anything with it: variables, data types, conditionals, loops, functions, arrays, objects, the DOM, and events. Every example below runs live in the page.
What Is JavaScript?
JavaScript is a programming language that runs in the browser and makes web pages interactive. It can read and change the page, respond to clicks and keystrokes, store data, make decisions, and communicate with servers — all without reloading.
It is a genuine programming language, not a markup language. It has variables, functions, conditionals, loops, and data structures. You can write real logic with it.
Structure
Headings, paragraphs, images, links. Describes what the content is.
Presentation
Colors, fonts, layout, spacing. Describes how the content looks.
Behavior
Clicks, responses, data, logic. Describes what the page does.
JavaScript is not Java
The name is a marketing decision from 1995. JavaScript and Java are entirely different languages — different syntax, different runtimes, different purposes. The name was chosen because Java was popular at the time.
JavaScript is not just for browsers. Node.js runs it on servers, Deno runs it as a command-line tool, React Native runs it on phones, and Electron runs it on the desktop. Learning JavaScript once gives you access to all of those.
What JavaScript Is Used For
Nearly every interactive feature on the modern web is JavaScript. Here is what it handles in practice.
Responding to events
Clicks, key presses, form submissions, scrolls, hovers — JavaScript listens and reacts.
Changing the page live
Update text, add and remove elements, toggle classes — without reloading.
Validating forms
Check a field is filled, an email is valid, a password is long enough — before submitting.
Fetching data
Load posts, products, or search results from a server without a page refresh.
Storing data
Remember a user’s theme choice, save a draft, cache responses in the browser.
Animations and effects
Carousels, modals, smooth scrolling, loading spinners — all driven by JS.
Single-page apps
React, Vue, and Angular are JavaScript. They build entire applications in the browser.
Servers and tools
Node.js powers backends, build tools, and command-line utilities.
HTML is what exists. CSS is how it looks. JavaScript is what happens. When you find yourself wanting something to respond or change, that is a job for JavaScript.
How JavaScript Runs
Every modern browser includes a JavaScript engine that reads and executes your code. You do not install anything. You write JavaScript in an HTML file and open it in a browser.
The script element
JavaScript lives inside a <script> tag. The most common approach is a
separate .js file linked from the HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My Page</title>
</head>
<body>
<h1>Hello</h1>
<!-- Load the script at the end of the body -->
<script src="app.js"></script>
</body>
</html>
The app.js file contains JavaScript and nothing else — no <script>
tag, no HTML:
// app.js
const heading = document.querySelector('h1');
heading.textContent = 'Hello from JavaScript';
Where to put the script tag
Place the <script> tag at the end of the <body>, or in
the <head> with the defer attribute. Either approach ensures
the HTML exists before the script tries to find it.
<!-- Option 1: at the end of the body -->
<body>
<h1>Hello</h1>
<script src="app.js"></script>
</body>
<!-- Option 2: in the head, with defer -->
<head>
<script src="app.js" defer></script>
</head>
Your first script
Here is a complete page with JavaScript that changes the heading when you click a button. The preview below is live — try clicking.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>First Script</title>
<style>
body {
font-family: system-ui, sans-serif;
padding: 32px;
background: #f8fafc;
text-align: center;
}
h1 { color: #0f172a; margin: 0 0 16px; }
button {
padding: 12px 24px;
border: 0;
border-radius: 10px;
background: #0891b2;
color: #fff;
font: inherit;
font-weight: 600;
cursor: pointer;
}
button:hover { background: #0e7490; }
</style>
</head>
<body>
<h1 id="message">Click the button</h1>
<button id="myButton">Click me</button>
<script>
// 1. Find the elements on the page
const heading = document.getElementById('message');
const button = document.getElementById('myButton');
let clicks = 0;
// 2. Listen for a click on the button
button.addEventListener('click', function () {
clicks = clicks + 1;
heading.textContent = 'You clicked ' + clicks + ' time' + (clicks === 1 ? '' : 's');
});
</script>
</body>
</html>
Three things happen in that script. It finds the heading and the button by their IDs, it attaches a click handler to the button, and each time the button is clicked it increments a counter and updates the heading’s text.
Press F12 or right-click and choose Inspect, then open the Console tab. You can type JavaScript directly into it and run it against the current page. It is the fastest way to experiment.
Variables: Storing Values
A variable is a named container for a value. You declare it, give it a name, and assign it a value. Later you can read that value back by name.
let, const, and var
JavaScript has three keywords for declaring variables. They behave differently, and the modern convention is straightforward.
var name = 'Ada';
// Function-scoped, not block-scoped.
// Hoisted in a confusing way.
// Can be redeclared silently.
var name = 'Grace'; // no error!const name = 'Ada'; // cannot be reassigned
let count = 0; // can be reassigned
count = count + 1; // fine
name = 'Grace'; // TypeError!| Keyword | Can reassign? | Scope | Use it when… |
|---|---|---|---|
const |
No | Block | The value will not change |
let |
Yes | Block | The value must be updated |
var |
Yes | Function | Almost never in new code |
Start every variable with const. If you later find you need to reassign it,
change that one declaration to let. This makes it obvious at a glance which
values are meant to change and which are fixed.
const prevents reassigning the variable — it does not freeze the value. An
object or array declared with const can still have its contents changed:
const list = [1, 2]; list.push(3); is perfectly valid.
Data Types
Every value in JavaScript has a type. There are eight, but seven of them cover almost everything you will write.
Text — always wrapped in quotes. 'hello', "world", `hi`.
Any numeric value, integer or decimal. 42, 3.14, -7.
True or false. Nothing else. true, false.
Deliberately empty. You assign it yourself when you mean “no value”.
Not yet assigned. What JavaScript gives a variable with no value.
A collection of key-value pairs. { name: 'Ada', age: 36 }.
An ordered list. Technically a kind of object. [1, 2, 3].
A reusable block of code. Also a kind of object in JavaScript.
Checking a type
Use the typeof operator to find out what type a value is:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Data Types</title>
<style>
body {
font-family: system-ui, sans-serif;
padding: 24px;
background: #f8fafc;
font-size: 14px;
}
.row {
background: #fff;
border: 1px solid #e2e8f0;
border-radius: 8px;
padding: 10px 14px;
margin-bottom: 6px;
display: flex;
justify-content: space-between;
gap: 12px;
}
.val { font-family: ui-monospace, monospace; color: #0f172a; }
.type { color: #0891b2; font-weight: 700; }
</style>
</head>
<body>
<div id="output"></div>
<script>
const examples = [
{ value: 'hello', label: "'hello'" },
{ value: 42, label: '42' },
{ value: 3.14, label: '3.14' },
{ value: true, label: 'true' },
{ value: null, label: 'null' },
{ value: undefined, label: 'undefined' },
{ value: [1, 2, 3], label: '[1, 2, 3]' },
{ value: { a: 1 }, label: '{ a: 1 }' }
];
const output = document.getElementById('output');
examples.forEach(function (item) {
const row = document.createElement('div');
row.className = 'row';
row.innerHTML =
'<span class="val">' + item.label + '</span>' +
'<span class="type">' + typeof item.value + '</span>';
output.appendChild(row);
});
</script>
</body>
</html>
typeof null returns "object". This is a bug from the very first
version of JavaScript in 1995, and it was never fixed because too much code relies on it.
It is one of the few genuinely surprising things in the language.
Operators: Doing Things with Values
Arithmetic
10 + 3 // 13 — addition
10 - 3 // 7 — subtraction
10 * 3 // 30 — multiplication
10 / 3 // 3.333... — division
10 % 3 // 1 — remainder (modulo)
10 ** 3 // 1000 — exponent
Comparison — and the === rule
This is the single most important thing to get right early. JavaScript has two equality operators, and they behave very differently.
1 == '1' // true — converts types
0 == false // true
'' == false // true
null == undefined // true
// Surprising, and a common
// source of bugs.1 === '1' // false — different types
0 === false // false
'' === false // false
null === undefined // false
// Behaves the way you expect.
The same applies to inequality: use !== instead of !=.
Logical operators
true && true // true — AND: both must be true
true && false // false
true || false // true — OR: at least one must be true
false || false // false
!true // false — NOT: flips the value
Watch them work
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Comparison</title>
<style>
body { font-family: system-ui, sans-serif; padding: 24px; background: #f8fafc; font-size: 14px; }
.row {
background: #fff; border: 1px solid #e2e8f0; border-radius: 8px;
padding: 10px 14px; margin-bottom: 6px;
display: flex; justify-content: space-between; gap: 12px;
}
.expr { font-family: ui-monospace, monospace; color: #0f172a; }
.result { font-weight: 700; }
.true { color: #16a34a; }
.false { color: #e11d48; }
</style>
</head>
<body>
<div id="output"></div>
<script>
const checks = [
{ expr: "1 == '1'", result: 1 == '1' },
{ expr: "1 === '1'", result: 1 === '1' },
{ expr: "0 == false", result: 0 == false },
{ expr: "0 === false", result: 0 === false },
{ expr: "null == undefined", result: null == undefined },
{ expr: "null === undefined", result: null === undefined },
{ expr: "5 > 3", result: 5 > 3 },
{ expr: "5 <= 3", result: 5 <= 3 },
{ expr: "true && false", result: true && false },
{ expr: "true || false", result: true || false }
];
const output = document.getElementById('output');
checks.forEach(function (check) {
const row = document.createElement('div');
row.className = 'row';
row.innerHTML =
'<span class="expr">' + check.expr + '</span>' +
'<span class="result ' + check.result + '">' + check.result + '</span>';
output.appendChild(row);
});
</script>
</body>
</html>
Reach for === and !== every time. The loose versions are only
useful for a couple of specific checks, and using them by accident is one of the most
common beginner bugs.
Conditionals: Making Decisions
A conditional runs different code depending on whether something is true or false.
const age = 20;
if (age >= 18) {
console.log('You can vote');
} else {
console.log('Too young to vote');
}
The three forms
A plain if is the most common. Use else if when there are several
possibilities, and a ternary when you just need to pick one of two values.
// 1. if — do something, or skip it
if (score > 90) {
grade = 'A';
}
// 2. if / else if / else — choose one of several
if (score >= 90) {
grade = 'A';
} else if (score >= 80) {
grade = 'B';
} else if (score >= 70) {
grade = 'C';
} else {
grade = 'F';
}
// 3. ternary — a compact two-way choice
const label = isLoggedIn ? 'Log out' : 'Log in';
Truthy and falsy
In a condition, JavaScript converts any value to a boolean. A handful of values are falsy — everything else is truthy.
// The complete list of falsy values
false
0
-0
0n // BigInt zero
'' // empty string
null
undefined
NaN // "not a number"
// Everything else is truthy, including:
'0' // a non-empty string
'false' // a non-empty string
[] // an empty array
{} // an empty object
if ([]) runs the block, because an empty array is still an object. This is
a common surprise. To check whether an array has any items, use
if (list.length > 0).
Loops: Repeating Things
A loop repeats a block of code. There are several kinds, and the right choice depends on what you are iterating over.
// 1. for — repeat a set number of times
for (let i = 0; i < 5; i++) {
console.log(i); // 0, 1, 2, 3, 4
}
// 2. for...of — iterate over the items in an array
const fruits = ['apple', 'banana', 'cherry'];
for (const fruit of fruits) {
console.log(fruit); // apple, banana, cherry
}
// 3. while — repeat as long as a condition is true
let count = 0;
while (count < 3) {
console.log(count); // 0, 1, 2
count = count + 1;
}
// 4. forEach — a method on arrays
fruits.forEach(function (fruit) {
console.log(fruit);
});
Watch a loop run
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Loops</title>
<style>
body { font-family: system-ui, sans-serif; padding: 24px; background: #f8fafc; font-size: 14px; }
h3 { font-size: 13px; text-transform: uppercase; letter-spacing: 0.08em; color: #64748b; margin: 18px 0 8px; }
h3:first-child { margin-top: 0; }
.item {
display: inline-block;
background: #fff;
border: 1px solid #e2e8f0;
border-radius: 8px;
padding: 8px 12px;
margin: 0 6px 6px 0;
font-family: ui-monospace, monospace;
color: #0891b2;
}
.item--violet { color: #7c3aed; border-color: #ddd6fe; }
</style>
</head>
<body>
<h3>for loop — 1 to 6</h3>
<div id="out-for"></div>
<h3>for...of — an array of colors</h3>
<div id="out-of"></div>
<h3>forEach — with the index</h3>
<div id="out-each"></div>
<script>
// 1. A plain for loop
const outFor = document.getElementById('out-for');
for (let i = 1; i <= 6; i++) {
const span = document.createElement('span');
span.className = 'item';
span.textContent = i;
outFor.appendChild(span);
}
// 2. for...of over an array
const colors = ['teal', 'violet', 'amber', 'lime'];
const outOf = document.getElementById('out-of');
for (const color of colors) {
const span = document.createElement('span');
span.className = 'item item--violet';
span.textContent = color;
outOf.appendChild(span);
}
// 3. forEach with the index
const outEach = document.getElementById('out-each');
colors.forEach(function (color, index) {
const span = document.createElement('span');
span.className = 'item';
span.textContent = index + ': ' + color;
outEach.appendChild(span);
});
</script>
</body>
</html>
If you just need to visit every item in an array, for...of or
forEach reads better than a counting for loop. Use the plain
for when you need the index, need to skip items, or need to break out early.
Functions: Reusable Blocks of Code
A function is a named block of code you can run whenever you want, as many times as you want. It is the single most important building block in JavaScript.
Three ways to write one
// 1. Function declaration — hoisted, can be called before it appears
function greet(name) {
return 'Hello, ' + name + '!';
}
// 2. Function expression — assigned to a variable
const greet2 = function (name) {
return 'Hello, ' + name + '!';
};
// 3. Arrow function — shorter, no own `this`
const greet3 = (name) => {
return 'Hello, ' + name + '!';
};
// Arrow with an implicit return — one expression, no braces
const greet4 = (name) => 'Hello, ' + name + '!';
// All four do the same thing
greet('Ada'); // 'Hello, Ada!'
greet4('Grace'); // 'Hello, Grace!'
Parameters and return values
Parameters are the inputs a function accepts. return sends a value back to
whoever called it. A function with no return gives back
undefined.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Functions</title>
<style>
body { font-family: system-ui, sans-serif; padding: 24px; background: #f8fafc; font-size: 14px; }
.result {
background: #fff;
border: 1px solid #e2e8f0;
border-radius: 8px;
padding: 12px 16px;
margin-bottom: 8px;
font-family: ui-monospace, monospace;
color: #0f172a;
font-size: 13px;
}
.label { color: #64748b; display: block; font-size: 11px; text-transform: uppercase; letter-spacing: 0.08em; margin-bottom: 4px; }
</style>
</head>
<body>
<div id="output"></div>
<script>
// Function declaration
function add(a, b) {
return a + b;
}
// Arrow function with implicit return
const square = (n) => n * n;
// Arrow function with a default parameter
const greet = (name = 'friend') => 'Hello, ' + name + '!';
// Function with a conditional inside
function grade(score) {
if (score >= 90) return 'A';
if (score >= 80) return 'B';
if (score >= 70) return 'C';
return 'F';
}
const output = document.getElementById('output');
function show(label, value) {
const div = document.createElement('div');
div.className = 'result';
div.innerHTML = '<span class="label">' + label + '</span>' + value;
output.appendChild(div);
}
show('add(3, 4)', add(3, 4));
show('square(7)', square(7));
show("greet('Ada')", greet('Ada'));
show('greet() with no argument', greet());
show('grade(95)', grade(95));
show('grade(72)', grade(72));
show('grade(58)', grade(58));
</script>
</body>
</html>
function log(msg) { console.log(msg); } returns undefined, not
the message. If you need a value back, you must return it explicitly.
Arrays and Objects
These are the two data structures you will use constantly. An array is an ordered list; an object is a labelled collection.
Arrays
const fruits = ['apple', 'banana', 'cherry'];
// Access by index — counting starts at 0
fruits[0] // 'apple'
fruits.length // 3
// Add and remove
fruits.push('date'); // add to the end
fruits.pop(); // remove from the end
fruits.unshift('avocado'); // add to the start
// Find things
fruits.indexOf('banana'); // 1
fruits.includes('apple'); // true
// Transform — the methods you will use most
const nums = [1, 2, 3, 4, 5];
nums.map(n => n * 2); // [2, 4, 6, 8, 10]
nums.filter(n => n > 2); // [3, 4, 5]
nums.reduce((sum, n) => sum + n, 0); // 15
nums.find(n => n > 3); // 4
Objects
const user = {
name: 'Ada',
age: 36,
email: 'ada@example.com',
isAdmin: true
};
// Access with dot notation
user.name // 'Ada'
// Or with bracket notation — useful when the key is in a variable
user['age'] // 36
// Add a property
user.country = 'UK';
// Check if a key exists
'name' in user // true
// Get the keys and values
Object.keys(user); // ['name', 'age', 'email', 'isAdmin', 'country']
Object.values(user); // ['Ada', 36, 'ada@example.com', true, 'UK']
Arrays of objects — the shape you will use most
In real applications, data almost always arrives as an array of objects. Rendering that list into the page is one of the most common tasks in JavaScript.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Arrays of Objects</title>
<style>
body { font-family: system-ui, sans-serif; padding: 24px; background: #f8fafc; font-size: 14px; }
.card {
background: #fff;
border: 1px solid #e2e8f0;
border-radius: 12px;
padding: 14px 16px;
margin-bottom: 10px;
}
.name { font-weight: 700; color: #0f172a; margin-bottom: 4px; }
.role { color: #0891b2; font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; }
</style>
</head>
<body>
<div id="team"></div>
<script>
const team = [
{ name: 'Ada Lovelace', role: 'Engineer' },
{ name: 'Grace Hopper', role: 'Admiral' },
{ name: 'Alan Turing', role: 'Researcher' }
];
const container = document.getElementById('team');
team.forEach(function (person) {
const card = document.createElement('div');
card.className = 'card';
card.innerHTML =
'<div class="name">' + person.name + '</div>' +
'<div class="role">' + person.role + '</div>';
container.appendChild(card);
});
</script>
</body>
</html>
Backtick strings let you embed values directly, which reads much better than concatenation
with +: `Hello, ${name}!` instead of
'Hello, ' + name + '!'.
The DOM: Talking to the Page
The DOM — Document Object Model — is the browser’s representation of your HTML as a tree of objects. JavaScript can read that tree, change it, and add or remove pieces of it. When the DOM changes, the browser re-renders the page.
Finding elements
// The modern way — CSS selectors
document.querySelector('.card'); // the first matching element
document.querySelectorAll('.card'); // all of them (a NodeList)
// Older ways, still common
document.getElementById('message'); // by id
document.getElementsByClassName('card');
document.getElementsByTagName('div');
// From another element
const card = document.querySelector('.card');
card.querySelector('.card__title'); // scoped search
Changing content and attributes
const heading = document.querySelector('h1');
// Text — safe, escapes anything you insert
heading.textContent = 'New heading';
// HTML — parses the string as HTML
heading.innerHTML = '<em>Italic</em> heading';
// Attributes
const link = document.querySelector('a');
link.setAttribute('href', 'https://example.com');
link.getAttribute('href');
// Classes
const card = document.querySelector('.card');
card.classList.add('card--featured');
card.classList.remove('card--featured');
card.classList.toggle('card--featured');
card.classList.contains('card--featured'); // true / false
// Styles (inline — prefer classes in real code)
card.style.backgroundColor = '#0891b2';
Creating and removing elements
// Create
const li = document.createElement('li');
li.textContent = 'A new item';
// Add it to the page
const list = document.querySelector('ul');
list.appendChild(li);
// Remove
li.remove();
innerHTML parses the string as HTML, which means untrusted input can inject
scripts — a security problem called XSS. Use textContent for anything that
came from a user or a server.
Events: Responding to the User
An event is something that happens on the page — a click, a keypress, a form submission, a scroll. An event listener is a function that runs when that event occurs.
const button = document.querySelector('#myButton');
button.addEventListener('click', function (event) {
console.log('The button was clicked');
console.log(event.target); // the element that was clicked
});
The events you will use most
| Event | Fires when… | Usually attached to |
|---|---|---|
click |
The element is clicked | Buttons, links, anything |
input |
The value of a field changes as you type | Text inputs, textareas |
change |
A field loses focus with a new value | Selects, checkboxes |
submit |
A form is submitted | Form elements |
keydown |
A key is pressed down | The document, an input |
mouseenter |
The pointer enters the element | Any element |
scroll |
The page or an element is scrolled | window, scrollable elements |
load |
The page has fully loaded | window |
A live counter
Here is a complete, working example that combines everything in this guide: variables, functions, the DOM, and events. The preview is live — try the buttons.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Counter</title>
<style>
body {
font-family: system-ui, sans-serif;
padding: 40px 24px;
background: #f8fafc;
text-align: center;
margin: 0;
}
.value {
font-size: 4rem;
font-weight: 700;
color: #0f172a;
margin: 0 0 8px;
font-variant-numeric: tabular-nums;
}
.label {
font-size: 0.82rem;
text-transform: uppercase;
letter-spacing: 0.1em;
color: #64748b;
margin: 0 0 28px;
}
.controls { display: flex; gap: 10px; justify-content: center; }
button {
width: 48px; height: 48px;
border: 1px solid #cbd5e1;
border-radius: 12px;
background: #fff;
font-size: 20px;
font-weight: 600;
color: #0f172a;
cursor: pointer;
transition: all 0.15s ease;
}
button:hover { background: #0891b2; color: #fff; border-color: #0891b2; }
button:active { transform: scale(0.95); }
</style>
</head>
<body>
<p class="value" id="value">0</p>
<p class="label">Current count</p>
<div class="controls">
<button id="decrease">−</button>
<button id="reset">↻</button>
<button id="increase">+</button>
</div>
<script>
// State
let count = 0;
// DOM references
const display = document.getElementById('value');
// A function that updates the page from state
function render() {
display.textContent = count;
// Change the color based on the value
if (count > 0) {
display.style.color = '#16a34a';
} else if (count < 0) {
display.style.color = '#e11d48';
} else {
display.style.color = '#0f172a';
}
}
// Event listeners
document.getElementById('increase').addEventListener('click', function () {
count = count + 1;
render();
});
document.getElementById('decrease').addEventListener('click', function () {
count = count - 1;
render();
});
document.getElementById('reset').addEventListener('click', function () {
count = 0;
render();
});
// Initial render
render();
</script>
</body>
</html>
Notice the structure. The count variable holds the state. The
render() function reads that state and updates the page. The event listeners
change the state and then call render(). That separation — state, render,
events — is the shape almost every interactive app takes, in JavaScript and in every
framework built on top of it.
Keep your data in variables, keep your DOM updates in one place, and let event listeners change the data and trigger a re-render. It is a pattern that scales from a counter to a full application.
Common JavaScript Mistakes
These are the errors that trip up nearly every beginner. Recognizing them early saves hours of debugging.
1. Using == instead of ===
if (userInput == 0) { }
// If userInput is the empty
// string '', this is true.
// If userInput is '0', this
// is also true.if (userInput === 0) { }
// Only true if userInput is
// the number 0. Exactly what
// you meant.2. Forgetting that the script runs before the DOM exists
<head>
<script src="app.js"></script>
</head>
// app.js:
const btn = document.querySelector('#myButton');
btn.addEventListener('click', ...);
// TypeError: Cannot read properties
// of null — the button has not
// been parsed yet.<body>
<button id="myButton">Click</button>
<script src="app.js"></script>
</body>
// Or in the head:
<script src="app.js" defer></script>
// Now the element exists when
// the script runs.3. Using var and getting surprising scope
for (var i = 0; i < 3; i++) {
// ...
}
console.log(i); // 3 — i still exists!
// var is function-scoped,
// not block-scoped.for (let i = 0; i < 3; i++) {
// ...
}
console.log(i); // ReferenceError
// let is block-scoped, which
// is what you expected.4. Mutating an array while iterating it
const nums = [1, 2, 3, 4, 5];
nums.forEach(function (n, i) {
if (n % 2 === 0) {
nums.splice(i, 1); // removes items
}
});
// Result is unpredictable.const nums = [1, 2, 3, 4, 5];
const odds = nums.filter(n => n % 2 !== 0);
// [1, 3, 5]
// The original is untouched.5. Forgetting to return
function double(n) {
n * 2; // computed, then thrown away
}
double(5); // undefinedfunction double(n) {
return n * 2;
}
double(5); // 106. Adding two strings when you meant two numbers
const a = '5'; // from an input field
const b = '3';
a + b // '53' — not 8!
// Input values are always
// strings.const a = Number('5');
const b = Number('3');
a + b // 8
// Or use parseInt for whole numbers.7. Expecting === to compare objects by value
{ a: 1 } === { a: 1 } // false
const x = { a: 1 };
const y = { a: 1 };
x === y; // false
// They are different objects,
// even though they look the same.const x = { a: 1 };
const y = { a: 1 };
x.a === y.a; // true
// Or use a deep comparison
// utility when needed.8. Using innerHTML with user input
const name = userInput.value;
output.innerHTML = '<p>Hi, ' + name + '</p>';
// If name contains:
// <img src=x onerror="...">
// the script runs.const name = userInput.value;
output.textContent = 'Hi, ' + name;
// Rendered as literal text.
// Nothing executes.JavaScript, unlike CSS, does report errors — in the browser console. If something does not work, open DevTools and read the first error. It almost always names the file, the line, and the exact problem.
Best Practices
These habits keep JavaScript readable as a project grows from a few lines to a few thousand.
Use const by default
Reach for const first, let when the value must change, and
avoid var entirely.
Always use ===
Strict equality avoids the type coercion surprises that == produces.
Name things clearly
userAge, not ua. isLoggedIn, not flag.
Keep functions small
A function that does one thing is easy to name, test, and reuse.
Separate state from rendering
Hold data in variables, update the page in one function, change data from events.
Read the console
It names the file, line, and problem. Check it before guessing.
Use textContent for user input
innerHTML with untrusted input opens the door to script injection.
Toggle classes, not styles
classList.toggle('is-open') keeps presentation in CSS where it belongs.
Comment the why
The code says what it does. A comment should say why it does it that way.
Use const, use ===, keep state in variables, render the page in
one place, and read the console when something breaks.
Frequently Asked Questions
1. What is JavaScript?
JavaScript is a programming language that runs in the browser and makes web pages interactive. It can respond to clicks, change content on the page, validate forms, fetch data from servers, and much more. It is the third layer of the web alongside HTML and CSS.
2. Is JavaScript the same as Java?
No. They are entirely different languages with different syntax, different purposes, and different runtimes. The name was a marketing decision in 1995. Java is a compiled language often used for backend and Android development; JavaScript is an interpreted language that runs in browsers and on Node.js.
3. Is JavaScript a programming language?
Yes. Unlike HTML, which is a markup language, JavaScript is a real programming language with variables, functions, conditionals, loops, and data structures. It can perform logic, manipulate data, and control program flow.
4. Do I need to install anything to use JavaScript?
No. Every modern browser includes a JavaScript engine, so you can write and run JavaScript by opening an HTML file. A code editor and a browser are enough to start. Node.js is only needed if you want to run JavaScript outside the browser.
5. What is the difference between let, const, and var?
let declares a variable that can be reassigned. const
declares a variable that cannot be reassigned. var is the older syntax and
has different scoping rules that cause confusing bugs. Use const by
default, let when the value must change, and avoid var in new
code.
6. What is the difference between == and ===?
== compares two values after converting them to the same type, which
produces surprising results. === compares both value and type without any
conversion. Almost always use === because it behaves the way you expect.
7. What is the DOM?
The DOM — Document Object Model — is the browser’s representation of your HTML as a tree of objects that JavaScript can read and change. When JavaScript modifies the DOM, the browser re-renders the page to reflect the change.
8. What is an event listener?
An event listener is a function that runs when something happens on the page, such as a
click, a keypress, or a form submission. You attach it to an element with
addEventListener, and the browser calls the function whenever that event
occurs.
9. What is the difference between null and undefined?
undefined means a variable has been declared but has no value yet, and is
what JavaScript assigns by default. null is a value you assign yourself to
mean deliberately empty. Use null when you want to say there is no value on
purpose.
10. Can JavaScript run outside the browser?
Yes. Node.js is a runtime that runs JavaScript on a server or on your machine. It is used for backend APIs, build tools, command-line utilities, and desktop apps. The language is the same, but the built-in APIs differ from the browser.
11. What is the difference between a function declaration and an arrow function?
A function declaration is hoisted, so it can be called before it is defined. An arrow
function is a shorter syntax that is not hoisted and does not have its own
this value. Arrow functions are ideal for short callbacks.
12. What should I learn after the basics of JavaScript?
After variables, functions, arrays, objects, and the DOM, the next steps are array
methods like map and filter, asynchronous JavaScript with
promises and async/await, fetching data from APIs, and finally
a framework such as React or Vue.
Key Takeaways
- JavaScript is the programming language of the web — it makes pages interactive.
- HTML is structure, CSS is presentation, JavaScript is behavior.
- JavaScript is not Java; the name is a historical accident.
- Every browser runs JavaScript; nothing needs to be installed.
- Use
constby default,letwhen a value must change, and avoidvar. - Always use
===instead of==to avoid type coercion surprises. - A function is a reusable block of code;
returnsends a value back. - Arrays are ordered lists; objects are labelled collections of key-value pairs.
- The DOM is the page as a tree of objects that JavaScript can change.
- Event listeners run a function when something happens on the page.
- The pattern to remember: keep state in variables, render in one function, change state from events.
- When something breaks, read the browser console — it names the exact problem.
What to Learn Next
Now that the fundamentals are in place, the next step is the array methods that make working with data pleasant. Start with JavaScript Array Methods and JavaScript Functions Explained.
From there, explore Working with the DOM, JavaScript Events, and JavaScript Objects. When you are ready to work with data, read Fetching Data with the Fetch API and Async and Await.
If you are still connecting the pieces, read What Is CSS?, HTML vs CSS, and How Web Browsers Work for the surrounding context.
Practice Challenge
The fastest way to learn JavaScript is to build something small that you can actually use. This exercise takes about thirty minutes and touches every concept in this guide.
- Create
index.htmlandapp.jsin the same folder. - In the HTML, add an
<input>for a task, a<button>to add it, and an empty<ul>to hold the list. Loadapp.jsat the end of the body. - In
app.js, declare aconstfor each of the three elements usingdocument.getElementById. - Create an empty array called
tasksto hold the data. - Write a function called
render()that clears the list and rebuilds it from thetasksarray usingforEachandcreateElement. - Add a click listener to the button that reads the input’s value, checks it is not empty with an
ifstatement, pushes it ontotasks, clears the input, and callsrender(). - Test it. Add three tasks. Confirm they appear in the list.
- Now add a delete button to each list item inside
render(), usingtasks.splicewith the index and then callingrender()again. - Add a
keydownlistener on the input so pressing Enter also adds a task. - Finally, add a counter above the list that shows how many tasks there are, using
tasks.length.
If you complete those steps, you have used variables, an array, a function, a conditional, a loop, DOM queries, DOM creation, and three different event listeners — the entire foundation of interactive JavaScript in one small app. Everything you learn next, from array methods to React components, builds directly on this pattern of holding data, rendering it, and responding to events.