What is THIS word in Javascript

A typical object-oriented programming (OOP) language such as Java or C# would refer to this as an instance of the class. However, JavaScript, being a prototype-based language, has a different viewpoint, which basically refers to the context in which the function is executed. Take a look at a simple example:

const Dog = {
 name: "Kam",
 bark: function() {
  console.log(`Woof! My name is ${this.name}`);
 }
};

Dog.bark(); 
// Woof! My name is Kam

Here, this in this.name is pointing to the Dog object, because the bark function is being invoked on Dog.

When this becomes complex

The value of this is not set until a function in which this is defined is actually called. In some scenarios, such as callbacks or event handlers, this may not behave as originally thought.

const Cat = {
  name: "Kam",
  meow: function() {
    setTimeout(function() {
      console.log(`Meow! My name is ${this.name}`);
    }, 100);
  }
};

Cat.meow(); 
// Meow! My name is undefined

We see undefined because the setTimeout function does not refer to the Cat object, but to the global window object.

Exploring Bind

Bind allows us to easily specify which particular object will be bound to this when a function or method is called. Here's an example:

let person1 = {
  name: 'Kamil',
  speak: function() {
    return `Hello, my name is ${this.name}`;
  },
};

let person2 = {
  name: 'KamilTwo',
};

let speakForPerson1 = person1.speak
let speakForPerson2 = person1.speak.bind(person2);
console.log(speakForPerson1()); 
// Hello, my name is undefined
console.log(speakForPerson2()); 
// Hello, my name is KamilTwo

Exploring Call

The call method is a predefined JavaScript method. It is a quick way to borrow a method from one object and apply it to another. Have a look at this:

let person1 = {
  greet: function(city, country) {
    return `Hello, I am ${this.name} from ${city}, ${country}.`;
  },
};

let person2 = {
  name: 'Kamil',
};

console.log(person1.greet.call('', 'Plock', 'Poland'))
// Hello, I am undefined from Plock, Poland.

console.log(person1.greet.call(person2, 'Plock', 'Poland'));
// Hello, I am Kamil from New York, USA.

Exploring Apply

Like the call method, apply lets us borrow methods. The main difference is that apply takes a single array of arguments. See the example below:

let person1 = {
  greet: function(city, country) {
    return `Hello, I am ${this.name} from ${city}, ${country}.`;
  },
};

let person2 = {
  name: 'Kamil',
};

console.log(person1.greet.apply('', ['Plock', 'Poland']))
// Hello, I am undefined from Plock, Poland.

console.log(person1.greet.apply(person2, ['Plock', 'Poland']));
// Hello, I am Kamil from New York, USA.

Maybe we should get rid of this word?

You see that it can be easy to forget some of the rules for using it, so is it possible to avoid that? The answer is yes, and to solve that we can use functions:

const Greeter = () => {
  function greet(name, city, country) {
    return `Hello, I am ${name} from ${city}, ${country}.`;
  }

  // function someXYZ() {
  //   console.log('someXYZ');
  // }

  return {
    greet,
    // someXYZ
  }
}

let person1 = {
  name: 'Kamil',
  city: 'Plock',
  country: 'Poland'
};

console.log(Greeter().greet(person1.name, person1.city, person1.country));
// Hello, I am Kamil from Plock, Poland.

Summary

In JavaScript, this is a context-sensitive keyword that can refer to different objects depending on where it is used. While it can often be complex to handle, mastering this concept can lead to cleaner, more efficient code.

Happy binding!