The Many Ways “this” changed within my Code, with the Help of Debugger and Console.log.

Within the snippet below, I have singled out two instance methods that are included within my web application. (Side note: the commented out ellipses (//…) can be ignored, as they only serve to show that there are other things within the code that I have omitted in this article because it doesn’t pertain to the topic at hand. )

class List {
//...
appendList(){
//...
}
renderListShowPage(e) {
//...
}
//...
}

Instance methods within classes deal with what the name suggests, instances of that class. In this case, these methods do not deal with the direct properties of the List class as a static method would. Instead, these methods are only accessible through being used on an instance of the List class.

“this”

class List {
//...
appendList(){
debugger
}
renderListShowPage(e) {
debugger
}
//...
}

In this snippet above, both instance methods include a debugger which will help us confirm what the value of this would be. When the application runs and either method is triggered by previous code that calls upon it, we will hit the debugger in the console.

As we can see, within these instance methods, the value of this is an INSTANCE of the List class. However, as previously noted, the value of this changes depending on how or where it is called.

Within my code, I have created a variable named title that represents an HTML element. I have decided to add an event listener to title so that when that HTML element is clicked, another page will render.

Within the addEventListener method, the first argument it must take is the type of event (a ‘click’ in this case) that will trigger what needs to happen. The second argument, the listener, would be the method that is executed upon the trigger.

class List {appendList(){
//...
let title = document.createElement("h1")
// time to add event listener
title.addEventListener("click", renderListShowPage)
//...
}
renderListShowPage(e) {
//...
}
//...
}

The method that will be executed when the HTML element is clicked is renderListShowPage.

Since I want renderListShowPage to be executed when I click on title, I need to call renderListShowPage on the title element. Here is where this comes in.

If the value of this is determined by what it is called on (what is to the left of the dot) or how a function is being called. I can safely say that within the addEventListener, the value of this would be title, the HTML Element.

Now, I can call renderListShowPage on this which is exactly what I need.

(But wait, wasn’t the value of this, inside of the appendList method an instance of the List class but now this is an HTML element? Yes, and no.

The value of this, within the execution context of the appendList method has not changed. However, within the addEventListener method, the execution context is different which means the value of this is different within that method.)

class List {appendList(){
//...
let title = document.createElement("h1")
title.addEventListener("click", this.renderListShowPage)
//...
}
renderListShowPage(e) {
debugger
this.appendPlayerForm()
}//...
}

Great! The addEventListener within the appendList method now successfully executes the renderListShowPage method when I click on the HTML element within the browser. We have now hit the debugger within the console.

I have added the debugger in order to demonstrate what the value of this is inside of the renderListShowPage method. As we figured out before, the value of this, within the addEventListener is the HTML element that the variable title represents. Now that we have entered the renderListShowPage method, through the debugger, we can see that the value of this is still that same HTML element.

Now we have run into an issue. Within the renderListShowPage method, I am also using this. However, I do not want this to be the HTML element from above, I need it to be an instance of the List class in order to execute another function.

.bind()

class List {appendList(){
//...
let title = document.createElement("h1")
title.addEventListener("click", this.renderListShowPage.bind(this)
//...
}
renderListShowPage(e) {
debugger
this.appendPlayerForm()
}//...
}

Now we are using .bind(this) within the Event Listener. The Event Listener still works as before and it brings us to the renderListShowPage method then hits the debugger. Through the debugger, we can see that the value of this within the renderListShowPage method is no longer the HTML element from before but an instance of the List class.

Why did the value of this change? It is because of .bind(). In simple terms, when we use the bind method on a function, we are essentially able to set the this that is within that function bind has been called on, equal to whatever parameter that is passed inside of bind. In the beginning, we already established that within the appendList method, the value of this was a list object which as a result is the value of this within the bind element.

This triggers the renderListShowPage method.
This debugger allows us to pause the code at this point and work in the console.
This is the value of this which can be seen inside of the browser’s console

Within this example addEventListener function, I am essentially talking to the renderListShowPage method and saying, “Hey there, get ready for the user to click on this element. When they do click on it, I do not want you to refer to the default value of this that will be passed to your function. So, to help you out, I am binding, or making, the value of the this that I want you to use, equal to the value of the string “hello”, you’re welcome.”

Arrow Functions

For example,

class List
appendList(){
title.addEventListener("click", function(){console.log(this)})
}
}
Inside the console.

Within the anonymous function above, the value of this is redefined to what the function is being executed on, which is the HTML element that is represented by the title variable

class List
appendList(){
title.addEventListener("click", () => {console.log(this)})
}
}

Within the arrow function, the value of this is not redefined based on what it is called on. Instead, the value of this refers to its value within the functions lexical scope. The current lexical scope is within the appendList instance method where the value of this equals an instance of the List class.

Understanding this and how to properly use it is definitely not the easiest Javascript topic to grasp. However, with the use of tools like debugger, console.log, official Javascript documentation, and of course, practice, this becomes more and more clear.

Software Engineering Student