JavaScript(JS) this Keyword

www.igif‮moc.aedit‬

JavaScript this Keyword

In JavaScript, the this keyword is a special variable that refers to the object that the current function is a method of, or that the function was called on. The value of this depends on how the function is called and the context in which it is called.

Here are some common examples of how this can be used in JavaScript:

  1. As a method of an object:
const person = {
  name: 'John',
  greet() {
    console.log(`Hello, my name is ${this.name}`);
  }
};

person.greet(); // logs "Hello, my name is John"

In this example, this refers to the person object, since greet() is called as a method of person.

  1. In a constructor function:
function Person(name) {
  this.name = name;
  this.greet = function() {
    console.log(`Hello, my name is ${this.name}`);
  }
}

const john = new Person('John');
john.greet(); // logs "Hello, my name is John"

In this example, this refers to the new Person object that is being created, since the Person function is being called with the new keyword.

  1. Using call() or apply() to set the value of this:
const person1 = { name: 'John' };
const person2 = { name: 'Jane' };

function greet() {
  console.log(`Hello, my name is ${this.name}`);
}

greet.call(person1); // logs "Hello, my name is John"
greet.call(person2); // logs "Hello, my name is Jane"

In this example, call() is used to set the value of this to person1 and person2 respectively, so that greet() is called with the correct context.

  1. In arrow functions:
const person = {
  name: 'John',
  greet: () => {
    console.log(`Hello, my name is ${this.name}`);
  }
};

person.greet(); // logs "Hello, my name is undefined"

In this example, since arrow functions do not have their own this value, the value of this is not set to person, and this.name returns undefined.

Understanding the behavior of this is important for writing correct and effective JavaScript code. It is also a common topic in JavaScript interviews, so it's worth studying and practicing.

this Inside Global Scope

In the global scope of JavaScript, the value of this depends on the execution context in which it is used. If the code is running in a browser environment, the value of this in the global scope refers to the global window object. In a Node.js environment, this in the global scope refers to the global object.

Here's an example in a browser environment:

console.log(this === window); // logs "true"

function sayHello() {
  console.log(this === window);
}

sayHello(); // logs "true"

In this example, this is equivalent to the window object, since the code is running in a browser environment.

However, if we run this same code in a Node.js environment, this would refer to the global object:

console.log(this === global); // logs "true"

function sayHello() {
  console.log(this === global);
}

sayHello(); // logs "true"

In general, it's considered good practice to avoid using this in the global scope, since its behavior can be unpredictable and can vary depending on the execution context. Instead, it's better to explicitly reference global objects or variables as needed.

this Inside Function

In JavaScript, the value of this inside a function depends on how the function is called. The most common ways to call a function in JavaScript are:

  1. As a function:
function sayHello() {
  console.log(this);
}

sayHello(); // logs the global object (window or global, depending on the environment)

In this case, this refers to the global object (window in a browser environment or global in a Node.js environment).

  1. As a method of an object:
const person = {
  name: 'John',
  sayHello() {
    console.log(this);
  }
};

person.sayHello(); // logs the person object

In this case, this refers to the person object, since sayHello() is called as a method of person.

  1. Using call() or apply() to set the value of this:
function sayHello() {
  console.log(this);
}

const person = { name: 'John' };

sayHello.call(person); // logs the person object

In this case, call() is used to set the value of this to person, so that sayHello() is called with the correct context.

  1. Using bind() to create a new function with a bound this value:
function sayHello() {
  console.log(this);
}

const person = { name: 'John' };
const sayHelloAsPerson = sayHello.bind(person);

sayHelloAsPerson(); // logs the person object

In this case, bind() is used to create a new function sayHelloAsPerson that has its this value bound to person, so that it always logs the person object when called.

The behavior of this inside a function can be tricky to understand, especially when dealing with nested functions or functions that are passed as arguments. It's important to keep in mind the context in which a function is being called, and to use the appropriate techniques (such as call(), apply(), or bind()) to set the value of this as needed.

this Inside Constructor Function

In JavaScript, a constructor function is a special type of function that is used to create objects. When a constructor function is called with the new keyword, a new object is created and the value of this inside the function is set to that new object.

Here's an example:

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

const john = new Person('John');
console.log(john.name); // logs "John"

In this example, Person is a constructor function that takes a name parameter and assigns it to the name property of this. When we create a new Person object with new Person('John'), a new object is created and the value of this inside the Person function is set to that new object. The name property of the new object is then set to the value of the name parameter ('John').

It's worth noting that when a constructor function is called without the new keyword, the value of this inside the function is not set to a new object, but to the global object (window in a browser environment or global in a Node.js environment). This can lead to unexpected behavior and should be avoided.

Here's an example of calling a constructor function without new:

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

const john = Person('John'); // no "new" keyword
console.log(john); // logs "undefined"
console.log(name); // logs "John"

In this example, calling Person('John') without new sets the value of this inside Person to the global object (window in a browser environment). The name property of the global object is then set to 'John'. Since the Person function doesn't return anything explicitly, john is undefined. This is a common mistake and should be avoided by always using the new keyword when calling constructor functions.

this Inside Object Method

In JavaScript, when a function is called as a method of an object, the value of this inside the function is set to the object itself. This allows the function to access and manipulate the object's properties and methods.

Here's an example:

const person = {
  name: 'John',
  sayHello() {
    console.log(`Hello, my name is ${this.name}.`);
  }
};

person.sayHello(); // logs "Hello, my name is John."

In this example, sayHello is a method of the person object. When we call person.sayHello(), the value of this inside the sayHello function is set to the person object, so this.name refers to the name property of the person object.

It's important to note that if you assign an object method to a variable and then call the method through the variable, the value of this inside the method will no longer refer to the object. Instead, it will refer to the global object (window in a browser environment or global in a Node.js environment), or undefined in strict mode.

Here's an example of calling an object method through a variable:

const person = {
  name: 'John',
  sayHello() {
    console.log(`Hello, my name is ${this.name}.`);
  }
};

const hello = person.sayHello;
hello(); // logs "Hello, my name is undefined."

In this example, we assign the sayHello method of the person object to the hello variable, and then call hello(). Since hello() is called without any object context, the value of this inside the sayHello function is set to the global object (or undefined in strict mode), so this.name is undefined.

To avoid this issue, you can use the bind() method to create a new function with a bound this value:

const person = {
  name: 'John',
  sayHello() {
    console.log(`Hello, my name is ${this.name}.`);
  }
};

const hello = person.sayHello.bind(person);
hello(); // logs "Hello, my name is John."

In this example, we use the bind() method to create a new function hello with a bound this value of person. When we call hello(), the value of this inside the sayHello function is set to the person object, so this.name refers to the name property of the person object.

this Inside Inner Function

In JavaScript, the value of this inside an inner function depends on how the inner function is called.

If the inner function is called as a method of an object, the value of this inside the inner function will be set to the object.

Here's an example:

const person = {
  name: 'John',
  sayHello() {
    function innerFunction() {
      console.log(`Hello, my name is ${this.name}.`);
    }
    innerFunction();
  }
};

person.sayHello(); // logs "Hello, my name is undefined."

In this example, innerFunction is an inner function of the sayHello method of the person object. When we call person.sayHello(), the sayHello method is called as a method of the person object, so the value of this inside the method is set to the person object. However, when we call innerFunction() inside the sayHello method, innerFunction is called without any object context, so the value of this inside innerFunction is set to the global object (or undefined in strict mode), so this.name is undefined.

To solve this problem, we can use a technique called "closure" to capture the value of this inside the outer function and use it inside the inner function. We can do this by assigning this to a variable inside the outer function and then using that variable inside the inner function.

Here's an example of using closure to capture the value of this inside an inner function:

const person = {
  name: 'John',
  sayHello() {
    const self = this;
    function innerFunction() {
      console.log(`Hello, my name is ${self.name}.`);
    }
    innerFunction();
  }
};

person.sayHello(); // logs "Hello, my name is John."

In this example, we assign this to the self variable inside the sayHello method. Then, inside the innerFunction, we use self instead of this to access the name property of the person object. Since self is a variable inside the sayHello method, it is in scope for the innerFunction and we can use it to access the correct this value.

this Inside Arrow Function

In JavaScript, the value of this inside an arrow function is based on the surrounding context in which the arrow function is defined.

Unlike regular functions, arrow functions do not have their own this value. Instead, the value of this inside an arrow function is always the same as the value of this in the surrounding context.

Here's an example:

const person = {
  name: 'John',
  sayHello: () => {
    console.log(`Hello, my name is ${this.name}.`);
  }
};

person.sayHello(); // logs "Hello, my name is undefined."

In this example, sayHello is an arrow function defined inside the person object. When we call person.sayHello(), the value of this inside the arrow function is based on the surrounding context in which it is defined, which is the global context. In this case, this refers to the global object (or undefined in strict mode), so this.name is undefined.

To access the correct this value inside an arrow function, you can define the arrow function as a property of an object and use the object context to access the correct this value:

const person = {
  name: 'John',
  sayHello: function() {
    const innerFunction = () => {
      console.log(`Hello, my name is ${this.name}.`);
    }
    innerFunction();
  }
};

person.sayHello(); // logs "Hello, my name is John."

In this example, sayHello is a regular function that defines an arrow function called innerFunction. When we call person.sayHello(), the value of this inside the sayHello function is set to the person object, so this refers to the person object. Inside sayHello, we define innerFunction as an arrow function, so the value of this inside innerFunction is based on the surrounding context in which it is defined, which is the sayHello function. Since this inside sayHello is set to the person object, this.name inside innerFunction refers to the name property of the person object.

this Inside Function with Strict Mode

In JavaScript, when you use the strict mode, the behavior of this is slightly different inside a function compared to when strict mode is not used.

When strict mode is used, if a function is called with this set to undefined or null, then this will remain undefined or null, respectively. This is in contrast to non-strict mode, where this would default to the global object in these cases.

Here's an example:

'use strict';

function sayHello() {
  console.log(`Hello, my name is ${this.name}.`);
}

sayHello(); // logs "Hello, my name is undefined."

In this example, we define a function called sayHello and call it without setting the value of this. Since we are using strict mode, this inside sayHello is set to undefined. Therefore, when we try to access the name property of this, we get undefined.

To avoid this problem, you can explicitly set the value of this inside the function using the bind, call, or apply methods:

'use strict';

const person = {
  name: 'John'
};

function sayHello() {
  console.log(`Hello, my name is ${this.name}.`);
}

sayHello.call(person); // logs "Hello, my name is John."

In this example, we define an object called person with a name property. Then, we define a function called sayHello and use the call method to set the value of this inside the function to person. Therefore, when we call sayHello, the value of this inside the function is set to person, and we can access the name property of person.