| Method | Syntax | Typical Use | Key Points |
|---|---|---|---|
| Inline | <button onclick="myFunction()">Click</button> |
Very small scripts or quick prototypes | Mixes markup with behaviour → hard to maintain. |
| Internal (in‑page) | <script>function myFunction(){…}</script> |
Page‑specific code, easy debugging | Still mixes structure and behaviour; not cached by the browser. |
| External | <script src="script.js"></script> |
Reusable code, separation of concerns, browser caching | Recommended for production sites. |
| ES6 Module | <script type="module" src="main.mjs"></script> |
Modern projects that need import/export of functions/objects | Modules are loaded with defer semantics, have their own scope and can import other modules. |
JavaScript reacts to events such as clicks, key presses, page loads, or network responses. The typical pattern is:
document.getElementById('btn')).addEventListener('click', handler)).click).<button id="outer">
Outer
<span id="inner">Inner</span>
</button>
<script>
const outer = document.getElementById('outer');
const inner = document.getElementById('inner');
// Capture phase (third argument true)
outer.addEventListener('click', e => {
console.log('Outer – capture');
}, true);
// Bubble phase (default)
outer.addEventListener('click', e => {
console.log('Outer – bubble');
});
inner.addEventListener('click', e => {
console.log('Inner – bubble');
// e.stopPropagation(); // uncomment to stop bubbling
});
</script>
document.getElementById(id) – returns a single element, fastest lookup.document.querySelector(selector) – returns the first element that matches a CSS selector.document.querySelectorAll(selector) – returns a static NodeList of all matches.| Method | What it changes | Performance impact |
|---|---|---|
textContent |
Plain text inside an element | Low – no HTML parsing, minimal re‑flow. |
innerHTML |
HTML markup inside an element | Higher – parses HTML, may cause re‑flow. |
insertAdjacentHTML(position, html) |
Inserts HTML at a specific position (beforebegin, afterbegin, beforeend, afterend) |
More efficient than setting innerHTML on large containers. |
element.append(...nodes) / element.prepend(...nodes) |
Inserts DOM nodes (no HTML parsing) | Fast – works with existing nodes. |
element.style.property = 'value'element.classList.add('active')element.classList.remove('active')element.classList.toggle('active')<ul id="tasks"></ul>
<input id="newTask" placeholder="Add a task">
<button id="addBtn">Add</button>
<script>
const list = document.getElementById('tasks');
const input = document.getElementById('newTask');
const btn = document.getElementById('addBtn');
btn.addEventListener('click', () => {
const text = input.value.trim();
if (!text) return; // simple validation
const li = document.createElement('li');
li.textContent = text;
li.classList.add('task-item');
list.appendChild(li);
input.value = '';
});
</script>
var.this.`Hello ${name}`).export / import to organise code.// quizHelper.mjs
export const questions = [
{ q: 'Capital of France?', a: 'Paris' },
{ q: '2 + 2 = ?', a: '4' }
];
export function checkAnswer(user, correct) {
return user.trim().toLowerCase() === correct.toLowerCase();
}
// main.mjs
import { questions, checkAnswer } from './quizHelper.mjs';
const feedback = document.getElementById('feedback');
document.getElementById('checkBtn').addEventListener('click', () => {
const user = document.getElementById('answer').value;
const correct = questions[0].a;
feedback.textContent = checkAnswer(user, correct) ? 'Correct!' : 'Wrong';
});
fetch or XMLHttpRequest.http module to create a server that listens for requests and sends responses.// server.js (run with: node server.js)
const express = require('express');
const app = express();
app.use(express.json()); // parse JSON bodies
let tasks = []; // in‑memory store
// Create
app.post('/api/tasks', (req, res) => {
const { text } = req.body;
if (!text) return res.status(400).json({ error: 'Missing text' });
const id = Date.now();
tasks.push({ id, text });
res.status(201).json({ id, text });
});
// Read
app.get('/api/tasks', (req, res) => {
res.json(tasks);
});
// Update
app.put('/api/tasks/:id', (req, res) => {
const task = tasks.find(t => t.id == req.params.id);
if (!task) return res.status(404).json({ error: 'Not found' });
task.text = req.body.text || task.text;
res.json(task);
});
// Delete
app.delete('/api/tasks/:id', (req, res) => {
tasks = tasks.filter(t => t.id != req.params.id);
res.status(204).end();
});
app.listen(3000, () => console.log('Server running on http://localhost:3000'));
// client.js (included as a module)
async function loadTasks() {
const resp = await fetch('/api/tasks');
const data = await resp.json();
// render data …
}
| Library / Framework | Typical Use in A‑Level Projects | Key Learning Point |
|---|---|---|
| jQuery | Simplifies DOM selection, event handling and AJAX. | Understanding abstraction over native APIs. |
| Chart.js | Creates responsive charts for data visualisation. | Integrates JavaScript with the <canvas> element. |
| D3.js | Advanced data‑driven visualisations (e.g., interactive maps). | Shows binding of data to DOM/SVG. |
| React / Vue (conceptual) | Component‑based UI design; useful for discussing modern web development. | Highlights the shift from imperative DOM manipulation to declarative UI. |
<meta name="viewport" content="width=device-width, initial-scale=1"><button id="menuBtn">Menu</button>
<nav id="mainNav" class="nav">…</nav>
<style>
.nav { display: none; }
.nav.open { display: block; }
@media (min-width: 768px) {
.nav { display: block !important; }
}
</style>
<script>
const btn = document.getElementById('menuBtn');
const nav = document.getElementById('mainNav');
btn.addEventListener('click', () => nav.classList.toggle('open'));
</script>
<button>, <nav>, <form>) so assistive technologies can identify them.aria-label, aria-expanded or role attributes for custom widgets.keydown events, tabindex="0" for non‑interactive elements).| Threat | Typical Attack Vector | Mitigation in JavaScript |
|---|---|---|
| Cross‑Site Scripting (XSS) | Injecting malicious HTML/JS via user input. | Sanitise/escape all data before inserting into the DOM; prefer textContent over innerHTML. |
| Cross‑Site Request Forgery (CSRF) | Tricking a logged‑in user into sending unwanted requests. | Include anti‑CSRF tokens in POST requests; set SameSite attribute on cookies. |
| Insecure Direct Object References (IDOR) | Manipulating URLs or parameters to access unauthorised data. | Never rely solely on client‑side checks; validate all inputs on the server. |
| Content Security Policy (CSP) | Browser‑enforced policy that restricts sources of scripts, styles, etc. | Set a CSP header (e.g., Content‑Security‑Policy: script-src 'self') on the server. |
innerHTML.textContent or DOM‑creation methods (createElement) over HTML strings.localStorage or sessionStorage.fetch('https://api.example.com/items')
.then(r => {
if (!r.ok) throw new Error('Network error');
return r.json();
})
.then(data => {
// use data …
})
.catch(err => console.error(err));
JSON.stringify() and JSON.parse() convert between objects and text.<canvas id="myChart" width="400" height="200"></canvas>
<script type="module">
import Chart from 'https://cdn.jsdelivr.net/npm/chart.js';
async function loadSales() {
const resp = await fetch('https://api.example.com/sales');
if (!resp.ok) throw new Error('Failed to load data');
return resp.json(); // expects [{ month:'Jan', value:120 }, …]
}
loadSales().then(data => {
const ctx = document.getElementById('myChart').getContext('2d');
new Chart(ctx, {
type: 'line',
data: {
labels: data.map(d => d.month),
datasets: [{
label: 'Sales',
data: data.map(d => d.value),
borderColor: 'steelblue',
fill: false
}]
}
});
});
</script>
Each stage maps directly to assessment objectives:
ESLint enforces coding standards and catches common mistakes.Create an account or Login to take a Quiz
Log in to suggest improvements to this note.
Your generous donation helps us continue providing free Cambridge IGCSE & A-Level resources, past papers, syllabus notes, revision questions, and high-quality online tutoring to students across Kenya.