
Functions and Events in JavaScript Programming
JavaScript is the language of interactive web pages, and the moment you want a button to do something when it is clicked, you hit the two ideas at the heart of the language: functions and events. If callbacks, event handlers, and 'why does my code run in the wrong order?' are confusing you, you are at the exact point where JavaScript stops being like other languages and starts being its own thing — and it is the point where a little guidance saves a lot of frustration.
Functions package logic you can reuse, and events are how a web page responds to the user. Together they are the foundation of every interactive site. This guide covers how JavaScript functions work, including the closures that trip people up, and how the event-driven model — code that runs in response to things happening — actually behaves.
Functions are values you can pass around
A JavaScript function is a reusable block of logic, but the idea that unlocks the language is that functions are values — you can store one in a variable, pass it to another function, and return one from a function. This is what makes JavaScript so flexible, and it is the basis of everything from event handling to modern frameworks.
const add = (a, b) => a + b; // an 'arrow function' stored in a variable
console.log(add(2, 3)); // 5
console.log(typeof add); // 'function' -- it's a valueThe compact arrow-function syntax you see above is the modern standard, and it is worth getting comfortable with early because it is everywhere in real code. But the deeper point is conceptual: because a function is just a value, you can hand it to something else to be called later. That single idea — a function you pass along to be run when the time is right — is the key that makes events, and much of JavaScript, make sense.
Callbacks: functions run later
A callback is a function you give to another piece of code to be called at some later point — when a task finishes, when a button is clicked, when data arrives. This is the pattern that runs the interactive web, and it is where beginners first feel that JavaScript executes 'out of order' compared to the top-to-bottom flow they are used to.
function doTwice(action) {
action();
action();
}
let count = 0;
doTwice(() => count++); // pass a function to be called
console.log(count); // 2Here a function is passed into doTwice and called twice inside it. This feels strange at first — you are not calling your function yourself, you are handing it over to be called — but it is the foundation of event handling. When you tell a button 'run this function when clicked', you are giving it a callback. Understanding that a callback is simply 'a function to run later, when something happens' demystifies the event model that the rest of JavaScript depends on.
Callbacks and the event-driven model are where JavaScript stops behaving like the step-by-step languages people start with, and the 'why does my code run in the wrong order?' confusion it produces is one of the most common reasons self-taught learners quietly give up. It is also one of the fastest things to fix with a clear explanation and a worked example. If this is where you are stuck, our JavaScript tutoring can get the model to click in a single focused session rather than weeks of frustration.
Events: making a page respond
An event is something that happens on a web page — a click, a keypress, the page finishing loading — and JavaScript lets you run a function in response. You attach a callback to an element with addEventListener, and from then on, whenever that event occurs, your function runs. This is how every interactive feature on the web is built.
const button = document.querySelector("#myButton");
button.addEventListener("click", () => {
console.log("Button was clicked!");
});
// the function runs each time the button is clickedThe mental shift here is important and is where the event-driven model clicks into place. Your code does not run in a straight line and finish; instead, it sets up handlers and then waits, responding to events as they happen, possibly for as long as the page is open. This is fundamentally different from a script that runs once top to bottom, and grasping it — that you are wiring up responses rather than dictating a sequence — is the leap from writing scripts to building interactive applications.
Closures: functions that remember
One of JavaScript's most powerful and most confusing features is the closure: a function remembers the variables from where it was created, even after that surrounding code has finished. This sounds abstract, but it is what lets a function keep private state, and it appears constantly in real code.
function makeCounter() {
let n = 0;
return () => ++n; // this inner function 'closes over' n
}
const next = makeCounter();
console.log(next()); // 1
console.log(next()); // 2 -- it remembered nThe inner function keeps access to n even after makeCounter has returned, so each call remembers and increments the same private value. Closures are genuinely tricky the first time, and they are a favourite interview topic precisely because they reveal whether someone understands how JavaScript really works. You do not need to master every subtlety immediately, but recognising that a function carries its surrounding variables with it explains a lot of otherwise-mysterious behaviour, especially inside loops and event handlers.
Closures are also intensely practical, not just an interview curiosity. Every time you attach an event handler that needs to remember something — which item was clicked, how many times an action has happened, a value from when the handler was set up — you are relying on a closure, whether you name it or not. This is why the concept is worth investing in early: it quietly underpins the interactive code you will write constantly. Learners who get a clear explanation of closures early find that a whole set of previously-confusing behaviours suddenly makes sense, which is one of the moments where an hour of good tutoring pays for itself many times over.
Asynchronous code: why JavaScript waits without stopping
The most distinctive thing about JavaScript is that it does not wait around. When your code asks for something that takes time — data from a server, a file, a timer — JavaScript does not freeze until it arrives. It moves on and runs your response later, through a callback, when the result is ready. This asynchronous behaviour is what keeps web pages responsive, and it is also what most confuses learners coming from other languages.
console.log("first");
setTimeout(() => console.log("third"), 0); // runs LATER
console.log("second");
// prints: first, second, thirdNotice the output order: even with a zero-millisecond delay, the callback runs after the straight-line code finishes. This surprises everyone at first, and it is the root of the 'my code runs in the wrong order' confusion. Modern JavaScript manages this with promises and the async/await syntax, which make asynchronous code read more like ordinary top-to-bottom code. You do not need to master all of it immediately, but understanding that JavaScript handles slow operations by scheduling a response rather than waiting is essential to everything from loading data to handling clicks, and it is a concept worth getting help with early because it underpins so much real-world code.
Default and rest parameters
JavaScript functions handle their inputs flexibly, and two features make them cleaner to write and use. Default parameters let you specify a fallback value for an argument the caller omits, so a function behaves sensibly even when called with fewer arguments. Rest parameters let a function accept any number of arguments, gathering the extras into an array.
const greet = (name = "friend") => `Hi, ${name}`;
console.log(greet()); // 'Hi, friend' -- used the default
console.log(greet("Ada")); // 'Hi, Ada'These features make functions more robust and pleasant to use — a function with sensible defaults does not break when called simply, and rest parameters let one function handle a variable workload cleanly. They are part of modern JavaScript's toolkit for writing functions that are flexible without being fragile, and using them well is a sign of code that anticipates how it will actually be called rather than assuming perfect inputs.
Where JavaScript beginners actually struggle with functions and events
- Not grasping that functions are values that can be passed around and run later.
- Confusion when callback-based code runs 'out of order' versus top to bottom.
- Not understanding the event-driven model — setting up handlers, then waiting.
- Closures behaving unexpectedly, especially inside loops.
- Mixing up defining a function and calling it when attaching event handlers.
How to master JavaScript functions and events
- Internalise that a function is a value you can store, pass, and return.
- Learn callbacks as 'a function to run later', which unlocks the event model.
- Practise the addEventListener pattern until wiring up responses is second nature.
- Work through closure examples slowly until 'the function remembers' makes sense.
- Watch the difference between passing a function and calling it in handlers.
Make the event model finally click
Callbacks, events, and closures are the ideas that separate people who write scripts from people who build interactive applications — and they are exactly the concepts that are hardest to grasp from reading alone, because they are about timing and flow rather than syntax. A good explanation with the right example collapses weeks of confusion into an afternoon. Our JavaScript tutoring in Burnaby and online specialises in these turning-point concepts, working from real, running code so the model sticks.
See how quickly it can come together. Book a free 30-minute consultation, tell us what is confusing about events or closures, and we will show you the idea that makes it make sense — across Metro Vancouver online, or in person in Burnaby. No obligation, and honest advice on whether tutoring is what you need.
