FAQ: Javascript and the DOM - Interactivity with onclick

This community-built FAQ covers the “Interactivity with onclick” exercise from the lesson “Javascript and the DOM”.

Paths and Courses
This exercise can be found in the following Codecademy content:

Web Development
Building Interactive JavaScript Websites

FAQs on the exercise Interactivity with onclick

There are currently no frequently asked questions associated with this exercise – that’s where you come in! You can contribute to this section by offering your own questions, answers, or clarifications on this exercise. Ask or answer a question by clicking reply (reply) below.

If you’ve had an “aha” moment about the concepts, formatting, syntax, or anything else with this exercise, consider sharing those insights! Teaching others and answering their questions is one of the best ways to learn and stay sharp.

Join the Discussion. Help a fellow learner on their journey.

Ask or answer a question about this exercise by clicking reply (reply) below!

Agree with a comment or answer? Like (like) to up-vote the contribution!

Need broader help or resources? Head here.

Looking for motivation to keep learning? Join our wider discussions.

Learn more about how to use this guide.

Found a bug? Report it!

Have a question about your account or billing? Reach out to our customer support team!

None of the above? Find out where to ask other questions here!

I am confused as to what I am doing wrong here…

It has to do with your placement of the event listener. It should not be inside the handler function.

function handler() {
    //
}
element.onclick = handler;

handler in this case would be your function, by reference only. This is known as a callback. That should get you through the lesson.

Something of note, though not a key to this lesson is that the handler is scoped to the event object (element) and as a declared function inherits that context so has a this object.

function turnButtonRed (){
  this.style.backgroundColor = "red";
  this.style.color = "white";
  this.innerHTML = "Red Button";
}

Don’t let that confuse you, though. Just make a note.

Were the handler to be an arrow function, we could not do this and would be forced to refer to the object directly.

element.style. ...

as this lesson has us do. That means this will also work,

const turnButtonRed = () => {
  element.style.backgroundColor = "red";
  element.style.color = "white";
  element.innerHTML = "Red Button";
}

Again, just something to note.

11 Likes

@mtf Thx! This is what I did and got through the exercise ;).

Why the function call after element.onclick = does not need the () as in element.onclick = turnButtonRed(); why does this not work properly? and why do we write the function after the onclick without the ().?

15 Likes

We are registering the event and giving it a callback that will be invoked on the event object, when the node is clicked. What we pass to the listener is just a reference to the function, not the invocation of that function. It is up to the handler to invoke this when that time comes.

28 Likes

Thank you very much! @mtf

4 Likes

Last line (line 9)
element.onclick = turnButtonRed;

I thought it must be
element.onclick = turnButtonRed();
since it was a function declaration in the lines before that (and not a function expression, i.e turnButtonRed is not a variable name)

or am I forgetting something? :flushed:

oh now that I’ve seen @mtf 's response…I’m still wrapping my head around it but thank you all :sweat_smile::sob:

5 Likes

Can someone please tell me the difference between
element.onclick = function turnButtonRed (){
element.style.backgroundColor = ‘red’;
element.style.color = ‘white’;
element.innerHTML = “Red Button”;
}
which seemed to work based on the tasked given and this
function turnButtonRed (){
element.style.backgroundColor = ‘red’;
element.style.color = ‘white’;
element.innerHTML = “Red Button”;
}
element.onclick = turnButtonRed;

In both cases, the first worked but didn’t pass while the second worked and passed. What’s the misconception?

1 Like

The turnButtonRed function is given as a callback, which references the physical function but does not invoke it. The function is invoked (triggered) by the event listener when a click event is detected.

Both forms are valid and work as expected, but the latter is more manageable since the listener doesn’t need to be maintained if the handler function is modified. It is the more typical usage we encounter in production code.

2 Likes

This is proper code for this excersize. No idea why you would access the element directly when inside the function, very poor design of this lesson

let element = document.querySelector(“button”);

function turnButtonRed (){
this.style.backgroundColor = ‘red’;
this.style.color = ‘white’;
this.innerHTML = ‘Red Button’;
}

element.onclick = turnButtonRed;

2 Likes

Were it the case of using ES5, your proposed approach would be alright, but in the manner of ES6 and arrow functions, we lose this as the execution context of the callback function. I’ll have to check, but was the onclick global event around in ES5?

const turnButtonRed = event => {
  target = event.target;
  target.style.backgroundColor = 'red';
  target.style.color = 'white';
  target.textContent = "Red Button";
};
element.onclick = turnButtonRed;

Since we are using a global event, that would mean there is a global event object, so, for browsers that support this, we can access that, globally, without a parameter.

const turnButtonRed = () => {
  target = event.target;
  target.style.backgroundColor = 'red';
  target.style.color = 'white';
  target.textContent = "Red Button";
};
element.onclick = turnButtonRed;
1 Like

I agree with your statement, though I have found that more tightly scoped code to be more readable, and therefore I prefer having older style function to arrow functions. I feel it also helps in scanning large blocks of code and discerning what objects are which.

I would also think that using the more classic .addEventListener() solves my issue with the implicit event object, though this comes later in the lesson.

Perhaps i get ahead of myself.

ES6 is more expressive/declarative. It doesn’t haunt any scope but fits the realm it is inserted into. That would be my take.

Events all bubble to the top of scope. That’s what I believe this new train of thought is leading to. Bring events to the most optimal point to pick up on. Then delegate and handle.

isn’t

function foo() {}

more expressive, in terms of clarity of intent than

const foo = () => {}

Perhaps philosophical. To each their own. And, in terms of hoisting, it leads to more flexibility to programming styles. If you like to stack your declarations at the bottom of your scope, you can.

It would be a mistake to think that I advocate for one or the other. The efficacy of the situation will always dictate.

const is_even = x => ! x % 2;

vs,

function is_even(x) {
  return ! x % 2;
}

What advantage can be found for either? It comes down to design, and the designer.

1 Like

not’ing a modulus - slick codes sir. :smiley:

1 Like

I’m struggling here as well and I still don’t get it despite @mtf’s explanation.

element.onclick = turnButtonRed

turnButtonRed seems to be a variable, right? if so, why (the ■■■■) is the following function assigned to the variable turnButtonRed?

function turnButtonRed (){
  element.style.backgroundColor = "red";
  element.style.color = "white";
  element.innerHTML = "Red Button";
}

I would only understand this, if the function had been assigned to the variable like this before:

const turnButtonRed = function turnButtonRed (){
  element.style.backgroundColor = "red";
  element.style.color = "white";
  element.innerHTML = "Red Button";
}

Assigning a function reference, or passing one by reference only to another function, does not invoke it.

function foo(bar) {
    return bar + bar;
}
faz = foo;
console.log(faz('baz'))    // bazbaz

We can invoke the reference anytime just as though it were the actual function.

Why is it that turnButtonRed doesn’t need to be invoked?

Why not: element.onclick = turnButtonRed();
instead of element.onclick = turnButtonRed;
?