DEV Community

Cover image for Demystifying 'this' in JavaScript
Pantelis Theodosiou
Pantelis Theodosiou

Posted on • Originally published at pantelis.theodosiou.me

Demystifying 'this' in JavaScript

Photo by Brad on Unspash

One of the core ideas of JavaScript is the this keyword, which is essential for figuring out the context in which a function is run. Nonetheless, many developers may find it confusing, particularly those who are unfamiliar with the language. This piece will examine the this keyword, its characteristics, and practical applications for it.

What is the "this" keyword?

Think of this as a magic pointer that indicates the context in which a function is operating. It's similar to having a code-cracking secret decoder ring that indicates your current location. Depending on how a function is called, this's value may vary dynamically. Let's dissect it using a few examples.

Default Binding

The global object, which is typically the browser's window object, is referred to as this when a function is called without any specific binding.

function sayHi() {
  console.log(this);
}

sayHi(); // Logs the global object (usually 'window' in a browser)
Enter fullscreen mode Exit fullscreen mode

In this case, this points to the global context because the function is called in the global scope.

Implicit Binding

Occasionally, this is implicitly associated with the function's owning object. When a function is used as an object's method, this occurs:

const person = {
  name: "Pantelis",
  greet: function() {
    console.log(`Hello, my name is ${this.name}`);
  }
};

person.greet(); // Logs "Hello, my name is Pantelis"
Enter fullscreen mode Exit fullscreen mode

Because the function is called within the context of person, this inside the greet method is bound to the person object in this instance.

Explicit Binding

Additionally, you can use methods like call(), apply(), and bind() to explicitly set the value of this.

Using call() and apply()

When contacting a JavaScript function, you can set this variable's value explicitly using the call() and apply() methods. Their handling of function arguments differs slightly, but otherwise they are fairly similar.

call()

The call() method is used to invoke a function and explicitly specify the value of this and any additional arguments as separate parameters.

function introduce(language) {
  console.log(`My name is ${this.name} and I code ${language}`);
}

const person = { name: "Pantelis" };
introduce.call(person, "JavaScript"); // Logs "My name is Pantelis and I code JavaScript"
Enter fullscreen mode Exit fullscreen mode

In this example above, call() sets this to the person object and passes the argument JavaScript to the introduce function.

apply()

The apply() method is similar to call(), but it accepts an array or an array-like object as the second parameter for passing arguments.

function introduce(language) {
  console.log(`My name is ${this.name} and I code ${language}`);
}

const person = { name: "Pantelis" };
introduce.apply(person, ["JavaScript"]); // Logs "My name is Pantelis and I code JavaScript"
Enter fullscreen mode Exit fullscreen mode

apply() sets this to the person object and passes the argument JavaScript in the above example, operating similarly to call().

Using bind()

bind() differs from call() and apply() methods. bind() creates a new function with the given this value but does not call the function right away. When you want to create a function with a fixed context for use at a later time, this can be helpful:

function introduce(language) {
  console.log(`My name is ${this.name} and I code ${language}`);
}

const person = { name: "Pantelis" };
const introducePantelis = introduce.bind(person, "JavaScript");

introducePantelis(); // Logs "My name is Pantelis and I code JavaScript"
Enter fullscreen mode Exit fullscreen mode

In this example, bind() creates a new function introducePantelis, which has a fixed this value set to the person object and a predefined argument JavaScript. You can call introducePantelis() later to execute the function with these predetermined values.

Use Cases

  • call() and apply() are suitable for immediately invoking functions with specific this values and arguments,
  • bind() is useful when you want to create a function with a predefined context and arguments for future use, often in event handlers or callbacks.

New Binding

this is automatically bound to the newly created object when you use a constructor function with the new keyword:

function Dog(name) {
  this.name = name;
}

const dog1 = new Dog("Rocky");
console.log(dog1.name); // Logs "Rocky"
Enter fullscreen mode Exit fullscreen mode

this in this instance refers to the recently formed object within the Dog function.

Arrow Functions and this

The way the arrow functions differs slightly. They take on the this value from the lexical context that surrounds them rather than having their own this binding:

const outer = {
  inner: () => {
    console.log(this);
  }
};

outer.inner(); // Logs the global object (window in a browser)
Enter fullscreen mode Exit fullscreen mode

Because it is defined in the global scope in this example, this inside the arrow function is the global object.

Gaining proficiency in JavaScript requires an understanding of the this keyword. You can write more efficient and maintainable code by understanding its behavior and putting the concepts of default binding, implicit binding, explicit binding, and new binding to use.

But be aware of common pitfalls as well, such as using arrow functions when dynamic binding is required or losing the this context in callback functions. If you practice a lot, you'll become an expert in JavaScript this very soon!


If you found this post helpful or enjoyed it, consider supporting me by buying me a coffee. Your support helps me create more valuable content. ☕ Thank you!

Top comments (0)