JavaScript Events
The apartment door has one bell. The button is #bell, and the word on it is press. Under it, #chime says silent. The markup has no onclick attribute, so bell.onclick starts as null. typeof null is "object" in JavaScript, so typeof bell.onclick is "object" too. It is not "null" and it is not "undefined". The comparison bell.onclick === null is true.
Putting a function in onclick does not ring the bell. The chime stays silent until bell.click() runs the function that sits in the slot. The property holds one function. Assign a second function and the first one is gone. One click does not run both. addEventListener is the next page; that page can stack listeners. This page does not call it.
bell.onclick = null empties the slot. A click after that leaves the chime text alone. Inside the handler, this is the button, so this.id is bell. The word on the button stays press. The page script clicks once. The line under the bell reads dong / 1 / bell. This page does not create an element and does not set a CSS property.
One slot on the button
The previous page built li nodes with createElement, then placed them with append, prepend, and insertBefore. This page does not build a node and does not read children. The page before that wrote style and classList on a paint chip. This page does not assign style. getElementById only hands you the button and the chime. The new idea is the onclick property: one function, or null.
What the slot holds
The button starts with press on it and silent under it. Read the rows in order. Each snippet starts from that fresh button, except the page row, which is the demo at the bottom. The page demo does not assign null.
📊 What the slot holds
| Moment | What onclick holds |
Chime text | Easy to mix up |
|---|---|---|---|
| before any assignment | null; typeof is "object" |
silent | reading typeof as "null" |
after the ding function, before click |
a function | silent | the assignment ringing the bell |
after click with ding |
that function | ding | the button text becoming ding |
dong replaces ding, then one click |
the dong function, not ding | dong | both functions running |
onclick = null, then click, fresh button |
null; typeof is "object" |
silent | a cleared slot still ringing |
page script, one click |
a function; this.id is bell |
dong | the line ending with silent |
onclick is a property on the element. With no handler, the value is null, and typeof null is still "object". Use === null when you want to know the slot is empty. Assigning the property stores the function. It does not call it. bell.click() fires a click and runs whatever function is in the slot right then. The call does not change the button’s own text. A second assignment overwrites the property. The first function object still exists in memory if you kept a name for it, and the property no longer points at it. onclick = null removes the handler. An HTML onclick attribute would fill the same slot; this button has no such attribute. An arrow function in this slot would not set this to the button. This page uses a plain function.
The slot starts empty
The file opens with the button and the paragraph. Nothing has been assigned. These four logs ask the property, its typeof, the chime, and the word on the button.
let bell = document.getElementById("bell");
let chime = document.getElementById("chime");
console.log(bell.onclick);
console.log(typeof bell.onclick);
console.log(chime.textContent);
console.log(bell.textContent);
The logs are null, object, silent, and press. The property is empty. typeof does not print null. The button and the chime still show the words from the markup.
The function waits
onclick = function ... stores the function. The body does not run on that line. The chime is still silent, and the property is no longer null.
let bell = document.getElementById("bell");
let chime = document.getElementById("chime");
bell.onclick = function () {
chime.textContent = "ding";
};
console.log(typeof bell.onclick);
console.log(chime.textContent);
console.log(bell.onclick === null);
The logs are function, silent, and false. You can see a function in the slot. The paragraph has not changed, because nothing called the function.
click runs the one in the slot
bell.click() runs the current handler. The chime becomes ding. The button text stays press. The slot still holds a function after the click.
let bell = document.getElementById("bell");
let chime = document.getElementById("chime");
bell.onclick = function () {
chime.textContent = "ding";
};
bell.click();
console.log(chime.textContent);
console.log(bell.textContent);
console.log(typeof bell.onclick);
The logs are ding, press, and function. One click, one change, and it is the paragraph that changes. The word press is still the button.
The second function replaces the first
This snippet starts from the fresh button again. ding is stored, then dong is stored over it, and only then comes one click. There is no click between the two assignments, so the chime never becomes ding in this run. After the click it is dong. bell.onclick === ding is false. bell.onclick === dong is true.
let bell = document.getElementById("bell");
let chime = document.getElementById("chime");
function ding() {
chime.textContent = "ding";
}
function dong() {
chime.textContent = "dong";
}
bell.onclick = ding;
bell.onclick = dong;
bell.click();
console.log(bell.onclick === ding);
console.log(bell.onclick === dong);
console.log(chime.textContent);
The logs are false, true, and dong. The name ding still refers to a function. The property does not. One click ran dong only.
null empties the slot
Run this on the fresh button. A function is assigned and then cleared before any click. bell.click() after null does not write dong. The chime stays silent. typeof is object again, because the value is null.
let bell = document.getElementById("bell");
let chime = document.getElementById("chime");
bell.onclick = function () {
chime.textContent = "dong";
};
bell.onclick = null;
bell.click();
console.log(bell.onclick);
console.log(typeof bell.onclick);
console.log(chime.textContent);
The logs are null, object, and silent. The function that would have written dong is not in the slot at click time. The page demo below does not clear the slot.
One line under the bell
The script sits at the end of the body, after the button and the paragraph exist. It stores one function, then calls click once. Inside the function, taps goes from 0 to 1, the chime becomes dong, and this.id is written to bell.dataset.who. The line joins the chime, the tap count, and that id. It does not write the button text.
<!DOCTYPE html>
<html>
<head>
<title>events — page</title>
</head>
<body>
<button id="bell" type="button">press</button>
<p id="chime">silent</p>
<p id="line">…</p>
<script>
let bell = document.getElementById("bell");
let chime = document.getElementById("chime");
let taps = 0;
bell.onclick = function () {
taps = taps + 1;
chime.textContent = "dong";
bell.dataset.who = this.id;
};
bell.click();
document.getElementById("line").textContent =
chime.textContent + " / " + taps + " / " + bell.dataset.who;
</script>
</body>
</html>
The line reads dong / 1 / bell. The chime is dong, not silent. The count is 1, because the script clicks once. The last token is the button id, from this inside the handler, not the word press. The button still says press. The next page is event listeners. It does not use this single onclick slot as its main tool.
Five rings to check
- Read
onclick,typeof bell.onclick, the chime, and the button text. The values are null, object, silent, and press. - Assign the ding function and do not click.
typeofis function, the chime is silent, andonclick === nullis false. - Call
bell.click()with that ding function. The chime is ding, the button is press, andtypeofis function. - Assign ding, then dong, then click once.
onclick === dingis false,onclick === dongis true, and the chime is dong. - On a fresh button, assign a function, set
onclickto null, then click. The values are null, object, and silent. Read the page line: dong / 1 / bell.
Where this bell tricks you
The button still says press. The slot held the wrong function, or it held nothing.
- Reading
typeof bell.onclickas"null"while the value isnull - Expecting the assignment itself to change the chime to ding
- Expecting both
dinganddongto run on one click after the second assignment - Expecting the button text to become ding
- Expecting
clickto change the chime afteronclick = null - Using an arrow function and expecting
this.idto be bell - Reading
event.targethere; these handlers take no argument, and the event object is a later page - Calling
addEventListenerhere; the next page stacks listeners - Building the button with
createElement; the previous page did that - Reading the line as silent / 0 / press
What stays with you
- With no handler,
bell.onclickis null andtypeof bell.onclickis object - Assigning a function leaves the chime silent until
click bell.click()with the ding function sets the chime to ding and leaves the button as press- A second assignment replaces the first, so one click runs dong only
onclick = nullthenclickon a fresh button leaves the chime silent- The page line reads dong / 1 / bell, and
this.idinside the handler is bell
🧠 Test Your Knowledge
Test Your Knowledge
Challenge yourself with this interactive quiz and see how well you understand the topic
📝 Instructions
- Read each question carefully
- Select the best answer for each question
- You can retake the quiz as many times as you want
- Your progress will be shown at the top