JavaScript(JS) this Keyword
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:
- 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
.
- 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.
- Using
call()
orapply()
to set the value ofthis
:
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.
- 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:
- 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).
- 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
.
- Using
call()
orapply()
to set the value ofthis
:
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.
- Using
bind()
to create a new function with a boundthis
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
.