Understanding "this" keyword in JavaScript

·

5 min read

"this" keyword in JavaScript is the most used and also confused by beginner software developers. It results from the fact that this keyword is used in a different way when it comes to JavaScript.
It refers to a particular object depending on how it is invoked. this keyword is essential in learning other advanced concepts in JavaScript. In this article, we are going to use examples to illustrate the use of this keyword in different aspects. There are various contexts in which this keyword can be used in JavaScript:

  • Global context

  • Function context

  • this in a Method

  • Arrow Functions

  • Event Handlers

  • Methods i.e. call(), apply(), and bind()

The JavaScript "this" is not a variable and cannot be changed since it is reserved.

The Global Context

When this keyword is used alone, or in the global scope, it refers to the global object like so:

var object = this
console.log(object === window)  //returns true

When used in the strict mode, this also refers to the global object in node or the window object

"use strict"
var object = this
console.log(object === window)  //returns true

Function Context

The value of this in a function relies on how the function is called. In a function without the "strict mode", it points to the global object equivalent to the window in a browser window and global in node.

Example

function thisKeyword() {
  console.log(this === window); //returns true
}
thisKeyword();

window.thisKeyword() is the same as calling the thisKeyword() function.

When this is used in a function in strict mode, it is set to undefined by JavaScript.

Example

"use strict"
function thisKeyword() {
  console.log(this === window);  //returns undefined
}
thisKeyword();

The strict mode was introduced in ECMAScript 5.1. To enable strict mode, you use the "strict mode" at the top of the JavaScript file. Strict mode applies to both outer and inner functions.

Arrow Functions

It is a feature introduced in ES6. It makes the writing of JavaScript functions easy, tidy, readable, and easy to maintain. Thanks to arrow functions. JavaScript is set lexically, meaning it is defined from the outer function.

Example

var foo = this;
let thisFunction = () => this;
console.log(thisFunction() === foo); //returns true

Hence arrow function does not create their own execution contexts

Event Handlers

this keyword in HTML event handlers refer to the elements receiving the events.

Example

<button onclick = "console.log(this)">click</button>

When the button is clicked, the following is seen in the console.

"<button onclick = "console.log(this)">click</button>"

It can be used to style the element receiving the event like so:

<button onclick = "this.style.color = 'red'">click</button>

Methods i.e. call(), apply(), bind()

In JavaScript, there are three special methods: call(), apply(), and bind() used in binding.

call() Method

In the call() method, the function to be called is passed as an argument to the call method.

Example

let getFullName = function(){
  console.log(`My name is ${this.firstName} ${this.secondName}`)
}
let user = {
  firstName: "John",
  secondName: "Tarus"
}
getFullName.call(user)

The call() method is invoked in the getFullName() function which outputs the full name of the user. The arguments passed to the call() method determine what this refers to. In this case, the user object is passed to the call() method binding it to the call() method. Thus this.firstName logs John and this.secondName logs Tarus hence logging “My name is John Tarus” in the console.

In our example we passed one argument to the call() method. Multiple arguments can be passed to it like so:

let getFullName = function(about1, about2){
  console.log(`My name is ${this.firstName} ${this.secondName}, a ${about1} from ${about2}`)
}
let user = {
  firstName: "John",
  secondName: "Tarus"
}
let about = ["Software Developer", "Kenya"]

getFullName.call(user, about[0], about[1])

In the above example, we have passed several arguments to the call() method.

The user object must be passed as the first argument. If the user object is passed as a second or third argument, it returns undefined value.

But here is a catch, we have to pass the arguments each at a time in the call() method. This can be tedious and our code becomes hard to read in a case where we have several parameters to pass. Here is where the apply() method comes in.

apply() Method

With the apply() method, we can easily pass arguments without the hassle of passing each to the method. The apply() method does the same job as the call() method only that it makes the passing of arguments easier and smarter in a way.

Example

let getFullName = function(about1, about2){
  console.log(`My name is ${this.firstName} ${this.secondName}, a ${about1} from ${about2}`)
}
let user = {
  firstName: "John",
  secondName: "Tarus"
}
let about = ["Software Developer", "Kenya"]

getFullName.apply(user, about)

Above we are able to pass the arguments in a smarter way

When you are dealing with a single or no value of arguments to pass, use the call() method otherwise use apply()

bind() Method

The bind() method is identical to the call() and apply() methods only that it does not call the function directly rather it returns a new function which is in turn called.

Example

let getFullName = function(about1, about2){
  console.log(`My name is ${this.firstName} ${this.secondName}, a ${about1} from ${about2}`)
}
let user = {
  firstName: "John",
  secondName: "Tarus"
}
let about = ["Software Developer", "Kenya"]

let newFunction = getFullName.bind(user, about[0], about[1])
newFunction()

A new function newFunction is returned which is in turn invoked as newFunction() rather than invoking the getFullName() function directly.

Conclusion

We follow the precedence below to determine the object this refers to

  1. Bind()
  2. Call() and apply()
  3. Object method
  4. Global scope

Thank you for reading to the end 😜🤑😍. Follow me on Twitter and LinkedIn for more content on JavaScript, node, and react.