A Button That Just Sits There
Open any HTML file, drop a button into it, and load it in a browser:
<button id="cheerBtn">Cheer 🎉</button>
You will see a perfectly good-looking button. It has a border, a label, maybe a nice shade of blue if you styled it with CSS. Click it as many times as you like — nothing happens. No counter increases, no message appears, no color changes. This is not a bug. HTML was never designed to react to anything. It describes structure: "there is a button here, and it says Cheer." CSS was never designed to react to clicks either; it describes appearance: "make that button blue, round the corners." Neither language has a concept of time or events. A page built only from HTML and CSS is a photograph — fixed the instant it loads.
Every interactive thing you actually use on the web works differently. When you type a wrong PIN on a net-banking page and see "Incorrect PIN" appear without the page reloading, when a shopping cart total updates the moment you change the quantity, when an IRCTC seat-availability button shows "checking..." and then a live number — in every one of these cases, a program is watching for something to happen and reacting to it in real time. That program is JavaScript. This chapter is about how it works, from the smallest building block (a variable holding a number) up to a fully working, clickable, counting button you can trace line by line.
What JavaScript Actually Is, and Where It Lives
JavaScript is a programming language, just like Python or C++, but it has one feature that makes it special for the web: every modern browser — Chrome, Firefox, Edge, Safari — has a JavaScript engine built into it. You do not need to install anything. You write JavaScript code, place it inside a <script> tag in an HTML file (or link it as a separate .js file), and the browser reads and runs it the moment it processes that part of the page.
By convention, the <script> tag is placed near the end of the <body>, just before the closing tag:
<body>
<button id="cheerBtn">Cheer 🎉</button>
<script>
// your JavaScript goes here
</script>
</body>
The reason is practical, not stylistic: the browser reads an HTML file from top to bottom. If your script tries to grab the button before the button has actually been parsed and created, it will fail to find it. Placing the script after the elements it needs to control guarantees those elements already exist by the time the script runs.
Every browser also ships a tool called the console — open it with the F12 key or right-click → Inspect → Console. It is where the command console.log(...) prints values, and it is the single most useful debugging tool you will use this year. Whenever you are unsure what a piece of code is doing, put a console.log next to it and read the console.
Storing Information: Variables
A variable is a labelled box that holds a value your program can read or change later. JavaScript gives you three keywords to create one: let, const, and an older one, var. For this chapter (and almost all modern JavaScript), you should use only the first two:
letcreates a variable whose value is allowed to change later.constcreates a variable whose value cannot be reassigned after it is set — use it for anything that should stay fixed, like a reference to a button on the page.
var is the original way JavaScript created variables before 2015, and it behaves in confusing ways around scope (it leaks out of blocks like if and loops in ways let does not). It still works and you will see it in old code, but there is no reason to write new code with it.
let claps = 0;
const maxClaps = 50;
claps = claps + 1; // allowed: claps changes to 1
maxClaps = 60; // ERROR: cannot reassign a const
Variable names in JavaScript must start with a letter, $, or _, cannot contain spaces, and by strong convention use "camelCase" for multi-word names: clapCount, not clap_count or ClapCount.
Data Types and a Trap Called Coercion
Every value in JavaScript has a type. The three you will use constantly are:
- Number —
87,3.5,-12. Unlike some languages, JavaScript does not separate integers and decimals into different types; they are all just "number." - String — text, written in quotes:
"Computer Science",'Grade 9', or using backticks for a template literal, which can embed variables directly using${...}. - Boolean — exactly two possible values,
trueorfalse. This is the type every comparison and everyifcondition produces.
You can check any value's type with the typeof operator:
let score = 87;
let subject = "Computer Science";
let passed = true;
console.log(typeof score); // "number"
console.log(typeof subject); // "string"
console.log(typeof passed); // "boolean"
Template literals make building messages far easier than gluing strings together:
let name = "Aanya";
let marks = 87;
console.log(`${name} scored ${marks} marks.`);
// Aanya scored 87 marks.
Here is where beginners get burned. JavaScript will often try to be "helpful" by silently converting one type into another to make an operation work — this is called type coercion, and it does not always do what you expect:
console.log("5" + 3); // "53" (the number 3 is converted to text, then joined)
console.log("5" - 3); // 2 (here "5" is converted to a number, then subtracted)
console.log(5 == "5"); // true (== ignores type differences and converts first)
console.log(5 === "5"); // false (=== compares type AND value; no conversion)
Trace the first line carefully: + between a string and a number makes JavaScript treat it as text-joining ("concatenation"), so "5" + 3 glues the characters together into the two-character string "53", not the number 8. The second line uses -, which has no meaning for text, so JavaScript instead converts "5" into the number 5 and does ordinary subtraction, giving 2. The rule to remember: always use === and !==, never == and !=, so that a stray string never silently masquerades as a number in your comparisons.
Operators: Making Comparisons and Decisions
Arithmetic operators (+ - * / %) work as you'd expect, with % giving the remainder of a division — useful for checking, say, whether a roll number is even: rollNumber % 2 === 0. Comparison operators (> < >= <= === !==) always evaluate to a boolean. Logical operators combine booleans: && (AND, both sides must be true), || (OR, at least one side true), ! (NOT, flips a boolean).
let marks = 40;
let attendance = 80;
console.log(marks >= 33); // true
console.log(marks >= 33 && attendance >= 75); // true && true → true
console.log(marks >= 90 || attendance >= 75); // false || true → true
These boolean results are what feed directly into decision-making.
Functions: Packaging Behavior You Can Reuse
A function is a named block of code you define once and can run ("call") as many times as you like, optionally feeding it different inputs (parameters) each time and getting a result back (return value).
function checkResult(marks) {
if (marks >= 33) {
return "Pass";
} else {
return "Fail";
}
}
console.log(checkResult(45)); // "Pass"
console.log(checkResult(20)); // "Fail"
Trace it: calling checkResult(45) runs the function body with the parameter marks set to 45. The condition 45 >= 33 evaluates to true, so the function executes return "Pass" and immediately hands that string back to whoever called it — here, console.log prints it. The second call, checkResult(20), sets marks to 20; 20 >= 33 is false, so the else branch runs and "Fail" is returned instead. Notice the function itself never printed anything — it only computed and returned a value. Defining a function does not run it; only calling it (writing its name followed by parentheses) does. Keep that sentence in mind — it becomes critical in the next section.
The DOM: How JavaScript "Sees" a Web Page
When the browser reads your HTML file, it does not keep it as plain text. It builds a live, in-memory tree of objects, one object per tag, called the Document Object Model, or DOM. JavaScript does not edit your HTML file directly — it reads and modifies this tree of objects, and the browser instantly redraws the screen to match whatever the tree currently says. This is the entire mechanism behind "interactivity": HTML builds the tree once; JavaScript reaches into that tree afterward and changes it.
Two things to notice in that diagram. First, the tree in part 1 is built exactly once, when the page loads — JavaScript does not create it, it only reads and edits it afterward. Second, the five-step chain in part 2 does not happen at page-load time; it happens later, whenever the user actually clicks. Between those two moments, your JavaScript code has already finished running once from top to bottom and is now just waiting, doing nothing, until an event arrives. This waiting-then-reacting pattern is the core idea behind everything the rest of this chapter builds.
Selecting Elements and Listening for Events
To let JavaScript reach into the DOM tree, you first need a reference to the specific node you want. The most common way for grade 9 CBSE work is document.getElementById(...), which searches the whole tree for an element with a matching id attribute and hands back that exact DOM object:
const cheerBtn = document.getElementById("cheerBtn");
const clapCount = document.getElementById("clapCount");
const is the right choice here: the variable cheerBtn itself never needs to point to a different element, even though the button's contents on screen will keep changing.
Once you hold a reference to an element, you can register a function to run whenever a particular event happens to it, using addEventListener. It takes two arguments: the event name as a string ("click", "mouseover", "keydown", and dozens more), and the function to run when that event fires:
cheerBtn.addEventListener("click", addClap);
Read that line precisely: it does not say "run addClap right now." It says "when a click ever happens on cheerBtn, run the function named addClap at that future moment." The function you pass is called a callback, because the browser calls it back later, on its own schedule, whenever the event occurs — possibly zero times, possibly a hundred times.
Full Worked Example: The Cheer Button
Now assemble every piece — a variable, DOM selection, a function, an event listener, and a decision — into one working page:
<button id="cheerBtn">Cheer 🎉</button>
<p>Claps: <span id="clapCount">0</span></p>
<p id="message"></p>
<script>
let claps = 0;
const cheerBtn = document.getElementById("cheerBtn");
const clapCount = document.getElementById("clapCount");
const message = document.getElementById("message");
function addClap() {
claps = claps + 1;
clapCount.textContent = claps;
if (claps === 10) {
message.textContent = "You are a Superfan!";
cheerBtn.style.backgroundColor = "gold";
}
}
cheerBtn.addEventListener("click", addClap);
</script>
Trace it exactly as the browser would. On page load, the script runs top to bottom once: claps is set to 0, the three const references are captured, the function addClap is defined (not run), and addEventListener registers it against future clicks. Nothing on screen changes yet — the span still shows the "0" that was already in the HTML.
Click 1: the browser fires a click event on cheerBtn, which runs addClap(). Inside it, claps = claps + 1 reads the current value of claps (0), adds 1, and stores 1 back into claps. The next line, clapCount.textContent = claps, writes the number 1 into that DOM node, and the browser redraws the span to show 1. The condition claps === 10 is false (1 is not 10), so the if block is skipped entirely.
Clicks 2 through 9 repeat exactly the same pattern — each time, claps increases by one and the span updates to match, while the if stays false.
Click 10: claps becomes 10, the span shows 10, and this time claps === 10 evaluates to true. The if block now runs: message.textContent is set to "You are a Superfan!" and cheerBtn.style.backgroundColor is set to "gold", which immediately recolors the button.
Click 11: claps becomes 11, the span shows 11, and claps === 10 is now false again (11 is not 10), so the if block does not run a second time. Notice, though, that the message and the gold color stay on screen — nothing in the code ever tells them to revert, so once the DOM has been changed, it stays changed until something explicitly changes it back. This is an important, often-missed idea: the DOM does not "reset itself" between events. Its state is exactly whatever the last piece of JavaScript left it as.
Two Bugs Every Beginner Writes
Misconception 1 — calling the function instead of naming it. A very common mistake is writing the event listener line like this:
cheerBtn.addEventListener("click", addClap()); // WRONG
The parentheses after addClap make this a function call, not a function reference. JavaScript evaluates addClap() immediately, while the page is loading, before any click has happened — running the counting logic once for no reason, and then passing addEventListener whatever addClap() returned (in this case, nothing, so undefined). The browser cannot register undefined as something to call later, so clicking the button afterward does nothing at all. The fix is to hand over the function's name, without parentheses, so the browser holds onto the function itself and calls it later: cheerBtn.addEventListener("click", addClap).
Misconception 2 — writing = where === was meant. Suppose the milestone check had accidentally been written as:
if (claps = 10) { // WRONG: assignment, not comparison
message.textContent = "You are a Superfan!";
}
A single = is the assignment operator, not comparison. This line does not ask "is claps equal to 10?" — it sets claps to 10 every single time, and then, because an assignment expression evaluates to the value that was just assigned (10, which JavaScript treats as truthy inside an if), the condition is true on every click, regardless of the real count. The result: the message and gold color would appear after the very first click, and claps would get forcibly reset to 10 on every click after that too, breaking the counter permanently. This is precisely why the comparison operator you reach for by default should always be ===, never a bare =.
Practice: Trace, Predict, Fix
- Without running any code, predict what each line prints:
console.log("9" + 1); console.log("9" - 1); console.log(9 === "9"); console.log(9 == "9"); - A student writes
let attempts = 0;once at the top of their script, then inside their click-handler function writesattempts = attempts + 1;. After the button is clicked 4 times, what value doesattemptshold? Explain why in one sentence, referring to how the variable's value carries over between calls. - Find and fix the bug:
const submitBtn = document.getElementById("submitBtn"); submitBtn.addEventListener("click", checkAnswer()); - Rewrite the
checkResultfunction from this chapter so that, instead of returning "Pass" or "Fail", it returns "Pass" only when marks are 33 or above and attendance (a second parameter) is 75 or above, and "Fail" otherwise. You will need a logical operator from the "Operators" section. - In the Cheer Button example, what would the span show immediately after the page loads, before any click? What DOM property is responsible for that initial value, and where was it set?
Summary
HTML builds structure and CSS builds appearance, but neither can react to anything — only JavaScript can. The browser loads your HTML into a live tree of objects called the DOM; JavaScript never edits the HTML file itself, only this in-memory tree, and the browser instantly redraws the screen whenever the tree changes. Variables (let for values that change, const for references that don't) hold your data; every value has a type (number, string, boolean), and mixing types without the strict operators ===/!== invites silent coercion bugs. Functions package reusable logic and only run when explicitly called. document.getElementById hands you a reference to a specific DOM node, and addEventListener registers a callback function that the browser will run later, whenever a chosen event actually occurs — not when the line of code executes. Put together, these five ideas — variables, types, functions, DOM references, and event listeners — are the entire mechanism behind every button, form, and live update you have ever clicked on the web.
Think About It
Think about this: How would you explain javascript fundamentals: making web pages interactive to a friend who has never seen a computer? What real-world analogy would you use? Imagine you had to build a system using these concepts — what would be your first step? Try this: before moving on, write down three things you learned and one question you still have.