JavaScript is the programming language of the web. While HTML provides structure and CSS handles appearance, JavaScript makes pages interactive โ responding to clicks, validating forms, fetching data, animating elements, and powering entire applications. It is the only programming language that runs natively in every web browser, making it the world’s most widely deployed language. In this lesson you will learn exactly what JavaScript is, where it runs, and how to write and execute your first lines of code.
What JavaScript Does
| Layer | Technology | Responsibility |
|---|---|---|
| Structure | HTML | Content and semantics โ headings, paragraphs, images, links |
| Presentation | CSS | Visual appearance โ colours, layout, fonts, spacing |
| Behaviour | JavaScript | Interactivity โ user events, dynamic updates, data, logic |
Where JavaScript Runs
| Environment | Runtime | Use Cases |
|---|---|---|
| Browser | V8 (Chrome/Edge), SpiderMonkey (Firefox), JavaScriptCore (Safari) | Web pages, web apps, browser extensions |
| Server | Node.js (V8) | APIs, CLIs, file systems, databases |
| Mobile | React Native, Expo | iOS and Android apps from JS code |
| Desktop | Electron | VS Code, Slack, Discord โ all built with JS |
| Edge / Cloud | Cloudflare Workers, Deno Deploy | Serverless functions at CDN edge nodes |
How JavaScript Gets into a Web Page
| Method | Syntax | When to Use |
|---|---|---|
| External file | <script src="app.js" defer></script> |
Always โ keeps HTML clean, cacheable, maintainable |
| Inline script | <script> /* code here */ </script> |
Small snippets, configuration โ avoid for large code |
| Inline event (avoid) | <button onclick="doSomething()"> |
Never in production โ mixes concerns, hard to maintain |
| ES module | <script type="module" src="app.js"></script> |
Modern apps โ enables import/export syntax |
<script> tags with the defer attribute in the <head> โ <script src="app.js" defer></script>. The defer attribute downloads the file in parallel with HTML parsing and executes it after the DOM is fully built. This is faster than the old convention of placing scripts at the bottom of <body>.myVariable, MyVariable, and MYVARIABLE are three completely different identifiers. A common beginner mistake is calling a function with the wrong capitalisation โ getElementById works; getElementByID throws a TypeError. Pay close attention to camelCase in JavaScript.Basic Example
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>What is JavaScript?</title>
<style>
body { font-family: system-ui, sans-serif; max-width: 600px; margin: 60px auto; padding: 0 24px; }
button {
padding: 12px 24px; background: #4f46e5; color: white;
border: none; border-radius: 8px; font-size: 1rem; cursor: pointer;
}
button:hover { background: #4338ca; }
#output {
margin-top: 24px; padding: 16px 20px;
background: #f1f5f9; border-radius: 8px;
font-size: 0.9rem; color: #334155; line-height: 1.6;
min-height: 48px;
}
</style>
</head>
<body>
<h1>Hello, JavaScript!</h1>
<p>Click the button โ JavaScript reacts to user events and updates the page dynamically.</p>
<button id="greetBtn">Say Hello</button>
<div id="output">Output will appear here...</div>
<script>
// 1. Select elements from the page
const btn = document.getElementById('greetBtn');
const output = document.getElementById('output');
// 2. Keep track of how many times the button was clicked
let clickCount = 0;
// 3. Listen for a click and run a function
btn.addEventListener('click', function () {
clickCount++; // increment the counter
// 4. Update the page content dynamically
output.textContent =
`Button clicked ${clickCount} time${clickCount === 1 ? '' : 's'}! ๐`;
// 5. Change button colour after 5 clicks
if (clickCount >= 5) {
btn.style.background = '#10b981';
btn.textContent = 'You found the easter egg! ๐';
}
});
// 6. Log a message to the browser DevTools console
console.log('JavaScript is loaded and ready.');
</script>
</body>
</html>
How It Works
Step 1 โ The Browser Parses HTML First
The browser reads the HTML top-to-bottom, building a tree of elements called the DOM (Document Object Model). When it reaches the <script> tag at the bottom of the body, the DOM is already built โ so JavaScript can immediately find and manipulate elements.
Step 2 โ document.getElementById Finds an Element
document.getElementById('greetBtn') searches the DOM for the element with id="greetBtn" and returns a reference to it. We store that reference in the btn variable so we can interact with it multiple times without searching the DOM again.
Step 3 โ addEventListener Wires Up Interactivity
btn.addEventListener('click', function() { ... }) tells the browser: “when this button is clicked, run this function.” The function is called an event handler. JavaScript does not run the function immediately โ it waits for the click event to fire.
Step 4 โ textContent Updates the Page
output.textContent = '...' sets the text content of the div. Every time the button is clicked, this line overwrites the previous value with a new string. The page updates instantly โ no reload required.
Step 5 โ console.log Writes to DevTools
Open your browser DevTools (F12 โ Console tab) to see the console.log output. The console is the primary debugging tool in JavaScript โ you can log variables, objects, errors, and messages throughout your code to understand what is happening at runtime.
Real-World Example: Dark Mode Toggle
<!DOCTYPE html>
<html lang="en" data-theme="light">
<head>
<meta charset="UTF-8">
<title>Dark Mode Toggle</title>
<style>
:root { color-scheme: light dark; }
[data-theme="light"] { --bg: #ffffff; --text: #0f172a; --surface: #f1f5f9; }
[data-theme="dark"] { --bg: #0f172a; --text: #f8fafc; --surface: #1e293b; }
body {
background: var(--bg);
color: var(--text);
font-family: system-ui, sans-serif;
padding: 40px 24px;
transition: background 0.3s ease, color 0.3s ease;
}
.toggle-btn {
padding: 10px 20px;
background: var(--surface);
color: var(--text);
border: 1.5px solid #e2e8f0;
border-radius: 8px;
font-size: 0.9rem;
cursor: pointer;
transition: background 0.2s;
}
</style>
</head>
<body>
<h1>Dark Mode Toggle</h1>
<button class="toggle-btn" id="themeToggle">🌙 Switch to Dark Mode</button>
<script>
const toggle = document.getElementById('themeToggle');
const html = document.documentElement; // the <html> element
toggle.addEventListener('click', function () {
const isDark = html.getAttribute('data-theme') === 'dark';
// Flip the theme
html.setAttribute('data-theme', isDark ? 'light' : 'dark');
// Update button label
toggle.textContent = isDark
? '๐ Switch to Dark Mode'
: 'โ๏ธ Switch to Light Mode';
// Persist preference so it survives page reload
localStorage.setItem('theme', isDark ? 'light' : 'dark');
});
// Restore saved preference on load
const saved = localStorage.getItem('theme');
if (saved) {
html.setAttribute('data-theme', saved);
toggle.textContent = saved === 'dark'
? 'โ๏ธ Switch to Light Mode'
: '๐ Switch to Dark Mode';
}
</script>
</body>
</html>
Common Mistakes
Mistake 1 โ Script loads before the DOM is ready
โ Wrong โ script in <head> without defer tries to find elements before they exist:
<head>
<script src="app.js"></script> <!-- DOM not built yet โ getElementById returns null -->
</head>
โ
Correct โ use defer so the script runs after the DOM is ready:
<head>
<script src="app.js" defer></script> <!-- waits for full DOM before executing -->
</head>
Mistake 2 โ Using inline onclick instead of addEventListener
โ Wrong โ mixes HTML and JavaScript, hard to maintain and test:
<button onclick="doThing()">Click</button>
โ Correct โ keep behaviour in JavaScript files:
document.getElementById('myBtn').addEventListener('click', doThing);
Mistake 3 โ Forgetting that JavaScript is case-sensitive
โ Wrong โ wrong capitalisation causes a TypeError at runtime:
document.getElementByID('title'); // TypeError: not a function
document.GetElementById('title'); // TypeError: not a function
โ Correct โ exact camelCase as defined in the API:
document.getElementById('title'); // correct
Quick Reference
| Concept | Example | Notes |
|---|---|---|
| External script (recommended) | <script src="app.js" defer></script> |
In <head> โ defer waits for DOM |
| Inline script | <script> console.log('hi'); </script> |
Small snippets only |
| Select element | document.getElementById('id') |
Returns element or null |
| Listen for event | el.addEventListener('click', fn) |
Preferred โ no inline HTML needed |
| Update content | el.textContent = 'New text' |
Safe โ does not parse HTML |
| Debug output | console.log(value) |
Open DevTools (F12) to view |
| ECMAScript versions | ES2015 (ES6), ES2020, ES2024 | New features added every year |