JavaScript's this keyword is notorious for confusing developers at all levels.
In this guide, we'll explore the inner workings of the 'this' keyword in JavaScript and how it behaves in different contexts.
It is commonly used in object-oriented programming languages to differentiate between class attributes and method parameters with the same name, as well as to access the current object's properties and methods
class Car {
// instance variables
type = 'hatchback';
// constructor
constructor(type) {
// this.type refers to the instance variable
// type refers to the parameter or argument of the constructor
this.type = type;
}
}We don't need to use this keyword when there is no ambiguity.
class Car {
model = 'Toyota';
constructor(modelArg) {
// There is no ambiguity here, so 'this' is not needed
model = modelArg;
}
}In JavaScript, the this keyword is a reference to an object, but its value depends on how and where it is used (Execution Context).
Here are the general rules for where this points to:
When used in the global context (outside of any function), this refers to the global object (window in browsers).
console.log(this); // window
console.log(this === window); // true
This behavior changes in strict mode, where this is undefined instead of the global object.
'use strict';
console.log(this); // undefined
console.log(this === window); // falseWhen used inside a function, this refers to the object that called the function.
const getThis = function() {
console.log(this);
}
// window, since getThis is called in the global context
getThis();Diagram Loading...
When function is a property of an object, this refers to the object itself.
const person = {
name: 'John',
sayName: function() {
console.log(this);
console.log(this.name);
}
}
// { name: 'John', sayName: [Function: sayName] }
// John
person.sayName();Diagram Loading...
If the function is assigned to a variable, this refers to the global object. (since its not part of the object anymore)
const { sayName } = person;
// window
// undefined
sayName();Diagram Loading...
When used inside a constructor function, this refers to the instance of the object being created.
class Person {
name = 'John';
constructor(name) {
this.name = name;
}
getName() {
console.log(this);
return this.name;
}
}
const person = new Person('Jane');
// { name: 'Jane', getName: [Function: getName] }
console.log(person.getName()); // Jane
Diagram Loading...
However, if the class function is assigned to a variable, this refers to undefined, as it is not part of the class anymore.
const { getName } = person;
getName(); // undefinedDiagram Loading...
JS executes classes in strict mode by default (mandated). This explains the difference in behavior between the "Function extracted from objects" and "Function extracted from classes" examples.
If the method is a static method, this refers to the constructor function (class) itself.
class Person {
value = 10;
static getValue() {
console.log(this); // [Function: Person]
return this.value; // undefined
}
}
console.log(Person.getValue()); // undefinedWhen used in a function constructor, this refers to the instance of the object being created.
function Person(name) {
this.name = name;
this.getName = function() {
return this.name;
}
}
const person = new Person('John');
person.getName(); // JohnDon't forget to use the new keyword when creating a new instance of the object. Forgetting to use the new keyword will result in global object pollution.
const person = Person('John');
console.log(person); // undefined
// global object pollution
// console.log(window.name); if you are using a browser
console.log(globalThis.name); // JohnWhen used as an event handler, this refers to the element that triggered the event.
document.body.addEventListener('click', function () {
console.log(this); // <body>
});Diagram Loading...
When used as a callback function for a timer, this refers to the Timer object.
setTimeout(function() {
console.log(this); // Timeout object
});const john = {
name: 'John',
sayName: function(arg1, arg2) {
console.log(this.name);
console.log({ arg1, arg2 });
}
}
const jane = {
name: 'Jane',
};If you want to explicitly set the value of this, you can use the following methods:
Executes a function with the execution context of another object.
john.sayName.call(jane, 'value1', 'value2');
// Jane { arg1: 'value1', arg2: 'value2' }Here sayHello() function is executed with the context of jane, instead of john.
Diagram Loading...
Similar to call(), but takes an array of arguments.
john.sayName.apply(jane, ['value1', 'value2']);
// Jane { arg1: 'value1', arg2: 'value2' }Creates a new bounded function that, when called, has its this keyword set to the provided value.
const boundFunction = john.sayName.bind(jane, 'value1', 'value2');
boundedFunction();
// Jane { arg1: 'value1', arg2: 'value2' }Javascript Arrow functions do not have their own this value. Instead, they inherit the this value from the enclosing lexical context.
Diagram Loading...
Object literals do not create a new lexical scope. The this value in this case refers to the scope in which the object was declared.
const person = {
name: 'John',
sayName: function() {
console.log(this);
console.log(this.name);
}
}
// { name: 'John', sayName: [Function: sayName] }
// John
person.sayName();class Person {
name = 'John';
constructor(name) {
this.name = name;
}
getName() {
return this?.name;
}
getNameArrow = () => {
return this?.name;
};
}
const person = new Person('Jane');function Person(name) {
this.name = name;
this.getName = function() {
return this.name;
}
this.getNameArrow = () => {
return this.name;
}
}
const person = new Person('John');When getName() and getNameArrow() function are called using the person instance. They both have the same value of this.
getName() - gets the this value from the person instance due to object context.getNameArrow() - gets the this value from the lexical context of the arrow function.person.getName(); // John
person.getNameArrow(); // JohnWhen getName() is called after being assigned to a variable, it loses its object context and this refers to the global object.
const { getName, getNameArrow } = person;
getName(); // undefined
getNameArrow(); // JohnUnderstanding the 'this' keyword is crucial for writing maintainable and bug-free code in JavaScript. It is a complex topic that requires practice to master.
By using arrow functions and explicit binding, you can avoid the confusion and pitfalls associated with the 'this' keyword.
It is commonly used in object-oriented programming languages to differentiate between class attributes and method parameters with the same name, as well as to access the current object's properties and methods
1class Car {
2 // instance variables
3 type = 'hatchback';
4
5 // constructor
6 constructor(type) {
7 // this.type refers to the instance variable
8 // type refers to the parameter or argument of the constructor
9 this.type = type;
10 }
11}We don't need to use this keyword when there is no ambiguity.
1class Car {
2 model = 'Toyota';
3
4 constructor(modelArg) {
5 // There is no ambiguity here, so 'this' is not needed
6 model = modelArg;
7 }
8}1class Car {
2 // instance variables
3 type = 'hatchback';
4
5 // constructor
6 constructor(type) {
7 // this.type refers to the instance variable
8 // type refers to the parameter or argument of the constructor
9 this.type = type;
10 }
11}1class Car {
2 model = 'Toyota';
3
4 constructor(modelArg) {
5 // There is no ambiguity here, so 'this' is not needed
6 model = modelArg;
7 }
8}In JavaScript, the this keyword is a reference to an object, but its value depends on how and where it is used (Execution Context).
Here are the general rules for where this points to:
When used in the global context (outside of any function), this refers to the global object (window in browsers).
console.log(this); // window
console.log(this === window); // true
This behavior changes in strict mode, where this is undefined instead of the global object.
'use strict';
console.log(this); // undefined
console.log(this === window); // falseWhen used inside a function, this refers to the object that called the function.
const getThis = function() {
console.log(this);
}
// window, since getThis is called in the global context
getThis();Diagram Loading...
When function is a property of an object, this refers to the object itself.
const person = {
name: 'John',
sayName: function() {
console.log(this);
console.log(this.name);
}
}
// { name: 'John', sayName: [Function: sayName] }
// John
person.sayName();Diagram Loading...
If the function is assigned to a variable, this refers to the global object. (since its not part of the object anymore)
const { sayName } = person;
// window
// undefined
sayName();Diagram Loading...
When used inside a constructor function, this refers to the instance of the object being created.
class Person {
name = 'John';
constructor(name) {
this.name = name;
}
getName() {
console.log(this);
return this.name;
}
}
const person = new Person('Jane');
// { name: 'Jane', getName: [Function: getName] }
console.log(person.getName()); // Jane
Diagram Loading...
However, if the class function is assigned to a variable, this refers to undefined, as it is not part of the class anymore.
const { getName } = person;
getName(); // undefinedDiagram Loading...
JS executes classes in strict mode by default (mandated). This explains the difference in behavior between the "Function extracted from objects" and "Function extracted from classes" examples.
If the method is a static method, this refers to the constructor function (class) itself.
class Person {
value = 10;
static getValue() {
console.log(this); // [Function: Person]
return this.value; // undefined
}
}
console.log(Person.getValue()); // undefinedWhen used in a function constructor, this refers to the instance of the object being created.
function Person(name) {
this.name = name;
this.getName = function() {
return this.name;
}
}
const person = new Person('John');
person.getName(); // JohnDon't forget to use the new keyword when creating a new instance of the object. Forgetting to use the new keyword will result in global object pollution.
const person = Person('John');
console.log(person); // undefined
// global object pollution
// console.log(window.name); if you are using a browser
console.log(globalThis.name); // JohnWhen used as an event handler, this refers to the element that triggered the event.
document.body.addEventListener('click', function () {
console.log(this); // <body>
});Diagram Loading...
When used as a callback function for a timer, this refers to the Timer object.
setTimeout(function() {
console.log(this); // Timeout object
});When used in the global context (outside of any function), this refers to the global object (window in browsers).
1console.log(this); // window
2
3console.log(this === window); // true
4This behavior changes in strict mode, where this is undefined instead of the global object.
1'use strict';
2
3console.log(this); // undefined
4
5console.log(this === window); // false1console.log(this); // window
2
3console.log(this === window); // true
41'use strict';
2
3console.log(this); // undefined
4
5console.log(this === window); // falseWhen used inside a function, this refers to the object that called the function.
1const getThis = function() {
2 console.log(this);
3}
4
5// window, since getThis is called in the global context
6getThis();Diagram Loading...
1const getThis = function() {
2 console.log(this);
3}
4
5// window, since getThis is called in the global context
6getThis();When function is a property of an object, this refers to the object itself.
1const person = {
2 name: 'John',
3 sayName: function() {
4 console.log(this);
5 console.log(this.name);
6 }
7}
8
9// { name: 'John', sayName: [Function: sayName] }
10// John
11person.sayName();Diagram Loading...
If the function is assigned to a variable, this refers to the global object. (since its not part of the object anymore)
1const { sayName } = person;
2
3// window
4// undefined
5sayName();Diagram Loading...
1const person = {
2 name: 'John',
3 sayName: function() {
4 console.log(this);
5 console.log(this.name);
6 }
7}
8
9// { name: 'John', sayName: [Function: sayName] }
10// John
11person.sayName();1const { sayName } = person;
2
3// window
4// undefined
5sayName();When used inside a constructor function, this refers to the instance of the object being created.
1class Person {
2 name = 'John';
3
4 constructor(name) {
5 this.name = name;
6 }
7
8 getName() {
9 console.log(this);
10 return this.name;
11 }
12}
13
14const person = new Person('Jane');
15
16// { name: 'Jane', getName: [Function: getName] }
17console.log(person.getName()); // Jane
18Diagram Loading...
However, if the class function is assigned to a variable, this refers to undefined, as it is not part of the class anymore.
const { getName } = person;
getName(); // undefinedDiagram Loading...
JS executes classes in strict mode by default (mandated). This explains the difference in behavior between the "Function extracted from objects" and "Function extracted from classes" examples.
If the method is a static method, this refers to the constructor function (class) itself.
class Person {
value = 10;
static getValue() {
console.log(this); // [Function: Person]
return this.value; // undefined
}
}
console.log(Person.getValue()); // undefined1class Person {
2 name = 'John';
3
4 constructor(name) {
5 this.name = name;
6 }
7
8 getName() {
9 console.log(this);
10 return this.name;
11 }
12}
13
14const person = new Person('Jane');
15
16// { name: 'Jane', getName: [Function: getName] }
17console.log(person.getName()); // Jane
181 const { getName } = person;
2getName(); // undefined1class Person {
2 value = 10;
3
4 static getValue() {
5 console.log(this); // [Function: Person]
6 return this.value; // undefined
7 }
8}
9
10console.log(Person.getValue()); // undefinedWhen used in a function constructor, this refers to the instance of the object being created.
1function Person(name) {
2 this.name = name;
3 this.getName = function() {
4 return this.name;
5 }
6}
7
8const person = new Person('John');
9person.getName(); // JohnDon't forget to use the new keyword when creating a new instance of the object. Forgetting to use the new keyword will result in global object pollution.
1const person = Person('John');
2console.log(person); // undefined
3
4// global object pollution
5// console.log(window.name); if you are using a browser
6console.log(globalThis.name); // John1function Person(name) {
2 this.name = name;
3 this.getName = function() {
4 return this.name;
5 }
6}
7
8const person = new Person('John');
9person.getName(); // John1const person = Person('John');
2console.log(person); // undefined
3
4// global object pollution
5// console.log(window.name); if you are using a browser
6console.log(globalThis.name); // JohnWhen used as an event handler, this refers to the element that triggered the event.
1document.body.addEventListener('click', function () {
2 console.log(this); // <body>
3});Diagram Loading...
1document.body.addEventListener('click', function () {
2 console.log(this); // <body>
3});When used as a callback function for a timer, this refers to the Timer object.
1setTimeout(function() {
2 console.log(this); // Timeout object
3});1setTimeout(function() {
2 console.log(this); // Timeout object
3});1const john = {
2 name: 'John',
3 sayName: function(arg1, arg2) {
4 console.log(this.name);
5 console.log({ arg1, arg2 });
6 }
7}
8
9const jane = {
10 name: 'Jane',
11};If you want to explicitly set the value of this, you can use the following methods:
Executes a function with the execution context of another object.
john.sayName.call(jane, 'value1', 'value2');
// Jane { arg1: 'value1', arg2: 'value2' }Here sayHello() function is executed with the context of jane, instead of john.
Diagram Loading...
Similar to call(), but takes an array of arguments.
john.sayName.apply(jane, ['value1', 'value2']);
// Jane { arg1: 'value1', arg2: 'value2' }Creates a new bounded function that, when called, has its this keyword set to the provided value.
const boundFunction = john.sayName.bind(jane, 'value1', 'value2');
boundedFunction();
// Jane { arg1: 'value1', arg2: 'value2' }1const john = {
2 name: 'John',
3 sayName: function(arg1, arg2) {
4 console.log(this.name);
5 console.log({ arg1, arg2 });
6 }
7}
8
9const jane = {
10 name: 'Jane',
11};Executes a function with the execution context of another object.
1john.sayName.call(jane, 'value1', 'value2');
2// Jane { arg1: 'value1', arg2: 'value2' }Here sayHello() function is executed with the context of jane, instead of john.
Diagram Loading...
1john.sayName.call(jane, 'value1', 'value2');
2// Jane { arg1: 'value1', arg2: 'value2' }Similar to call(), but takes an array of arguments.
1john.sayName.apply(jane, ['value1', 'value2']);
2// Jane { arg1: 'value1', arg2: 'value2' }1john.sayName.apply(jane, ['value1', 'value2']);
2// Jane { arg1: 'value1', arg2: 'value2' }Creates a new bounded function that, when called, has its this keyword set to the provided value.
1const boundFunction = john.sayName.bind(jane, 'value1', 'value2');
2boundedFunction();
3// Jane { arg1: 'value1', arg2: 'value2' }1const boundFunction = john.sayName.bind(jane, 'value1', 'value2');
2boundedFunction();
3// Jane { arg1: 'value1', arg2: 'value2' }Javascript Arrow functions do not have their own this value. Instead, they inherit the this value from the enclosing lexical context.
Diagram Loading...
Object literals do not create a new lexical scope. The this value in this case refers to the scope in which the object was declared.
1const person = {
2 name: 'John',
3 sayName: function() {
4 console.log(this);
5 console.log(this.name);
6 }
7}
8
9// { name: 'John', sayName: [Function: sayName] }
10// John
11person.sayName();class Person {
name = 'John';
constructor(name) {
this.name = name;
}
getName() {
return this?.name;
}
getNameArrow = () => {
return this?.name;
};
}
const person = new Person('Jane');function Person(name) {
this.name = name;
this.getName = function() {
return this.name;
}
this.getNameArrow = () => {
return this.name;
}
}
const person = new Person('John');When getName() and getNameArrow() function are called using the person instance. They both have the same value of this.
getName() - gets the this value from the person instance due to object context.getNameArrow() - gets the this value from the lexical context of the arrow function.person.getName(); // John
person.getNameArrow(); // JohnWhen getName() is called after being assigned to a variable, it loses its object context and this refers to the global object.
const { getName, getNameArrow } = person;
getName(); // undefined
getNameArrow(); // JohnObject literals do not create a new lexical scope. The this value in this case refers to the scope in which the object was declared.
1const person = {
2 name: 'John',
3 sayName: function() {
4 console.log(this);
5 console.log(this.name);
6 }
7}
8
9// { name: 'John', sayName: [Function: sayName] }
10// John
11person.sayName();1const person = {
2 name: 'John',
3 sayName: function() {
4 console.log(this);
5 console.log(this.name);
6 }
7}
8
9// { name: 'John', sayName: [Function: sayName] }
10// John
11person.sayName();1class Person {
2 name = 'John';
3
4 constructor(name) {
5 this.name = name;
6 }
7
8 getName() {
9 return this?.name;
10 }
11
12 getNameArrow = () => {
13 return this?.name;
14 };
15}
16
17const person = new Person('Jane');function Person(name) {
this.name = name;
this.getName = function() {
return this.name;
}
this.getNameArrow = () => {
return this.name;
}
}
const person = new Person('John');When getName() and getNameArrow() function are called using the person instance. They both have the same value of this.
getName() - gets the this value from the person instance due to object context.getNameArrow() - gets the this value from the lexical context of the arrow function.person.getName(); // John
person.getNameArrow(); // JohnWhen getName() is called after being assigned to a variable, it loses its object context and this refers to the global object.
const { getName, getNameArrow } = person;
getName(); // undefined
getNameArrow(); // John1class Person {
2 name = 'John';
3
4 constructor(name) {
5 this.name = name;
6 }
7
8 getName() {
9 return this?.name;
10 }
11
12 getNameArrow = () => {
13 return this?.name;
14 };
15}
16
17const person = new Person('Jane');1function Person(name) {
2 this.name = name;
3
4 this.getName = function() {
5 return this.name;
6 }
7
8 this.getNameArrow = () => {
9 return this.name;
10 }
11}
12
13const person = new Person('John');1person.getName(); // John
2person.getNameArrow(); // John1const { getName, getNameArrow } = person;
2getName(); // undefined
3getNameArrow(); // JohnUnderstanding the 'this' keyword is crucial for writing maintainable and bug-free code in JavaScript. It is a complex topic that requires practice to master.
By using arrow functions and explicit binding, you can avoid the confusion and pitfalls associated with the 'this' keyword.
It is commonly used in object-oriented programming languages to differentiate between class attributes and method parameters with the same name, as well as to access the current object's properties and methods
1class Car {
2 // instance variables
3 type = 'hatchback';
4
5 // constructor
6 constructor(type) {
7 // this.type refers to the instance variable
8 // type refers to the parameter or argument of the constructor
9 this.type = type;
10 }
11}We don't need to use this keyword when there is no ambiguity.
1class Car {
2 model = 'Toyota';
3
4 constructor(modelArg) {
5 // There is no ambiguity here, so 'this' is not needed
6 model = modelArg;
7 }
8}1class Car {
2 // instance variables
3 type = 'hatchback';
4
5 // constructor
6 constructor(type) {
7 // this.type refers to the instance variable
8 // type refers to the parameter or argument of the constructor
9 this.type = type;
10 }
11}1class Car {
2 model = 'Toyota';
3
4 constructor(modelArg) {
5 // There is no ambiguity here, so 'this' is not needed
6 model = modelArg;
7 }
8}In JavaScript, the this keyword is a reference to an object, but its value depends on how and where it is used (Execution Context).
Here are the general rules for where this points to:
When used in the global context (outside of any function), this refers to the global object (window in browsers).
console.log(this); // window
console.log(this === window); // true
This behavior changes in strict mode, where this is undefined instead of the global object.
'use strict';
console.log(this); // undefined
console.log(this === window); // falseWhen used inside a function, this refers to the object that called the function.
const getThis = function() {
console.log(this);
}
// window, since getThis is called in the global context
getThis();Diagram Loading...
When function is a property of an object, this refers to the object itself.
const person = {
name: 'John',
sayName: function() {
console.log(this);
console.log(this.name);
}
}
// { name: 'John', sayName: [Function: sayName] }
// John
person.sayName();Diagram Loading...
If the function is assigned to a variable, this refers to the global object. (since its not part of the object anymore)
const { sayName } = person;
// window
// undefined
sayName();Diagram Loading...
When used inside a constructor function, this refers to the instance of the object being created.
class Person {
name = 'John';
constructor(name) {
this.name = name;
}
getName() {
console.log(this);
return this.name;
}
}
const person = new Person('Jane');
// { name: 'Jane', getName: [Function: getName] }
console.log(person.getName()); // Jane
Diagram Loading...
However, if the class function is assigned to a variable, this refers to undefined, as it is not part of the class anymore.
const { getName } = person;
getName(); // undefinedDiagram Loading...
JS executes classes in strict mode by default (mandated). This explains the difference in behavior between the "Function extracted from objects" and "Function extracted from classes" examples.
If the method is a static method, this refers to the constructor function (class) itself.
class Person {
value = 10;
static getValue() {
console.log(this); // [Function: Person]
return this.value; // undefined
}
}
console.log(Person.getValue()); // undefinedWhen used in a function constructor, this refers to the instance of the object being created.
function Person(name) {
this.name = name;
this.getName = function() {
return this.name;
}
}
const person = new Person('John');
person.getName(); // JohnDon't forget to use the new keyword when creating a new instance of the object. Forgetting to use the new keyword will result in global object pollution.
const person = Person('John');
console.log(person); // undefined
// global object pollution
// console.log(window.name); if you are using a browser
console.log(globalThis.name); // JohnWhen used as an event handler, this refers to the element that triggered the event.
document.body.addEventListener('click', function () {
console.log(this); // <body>
});Diagram Loading...
When used as a callback function for a timer, this refers to the Timer object.
setTimeout(function() {
console.log(this); // Timeout object
});When used in the global context (outside of any function), this refers to the global object (window in browsers).
1console.log(this); // window
2
3console.log(this === window); // true
4This behavior changes in strict mode, where this is undefined instead of the global object.
1'use strict';
2
3console.log(this); // undefined
4
5console.log(this === window); // false1console.log(this); // window
2
3console.log(this === window); // true
41'use strict';
2
3console.log(this); // undefined
4
5console.log(this === window); // falseWhen used inside a function, this refers to the object that called the function.
1const getThis = function() {
2 console.log(this);
3}
4
5// window, since getThis is called in the global context
6getThis();Diagram Loading...
1const getThis = function() {
2 console.log(this);
3}
4
5// window, since getThis is called in the global context
6getThis();When function is a property of an object, this refers to the object itself.
1const person = {
2 name: 'John',
3 sayName: function() {
4 console.log(this);
5 console.log(this.name);
6 }
7}
8
9// { name: 'John', sayName: [Function: sayName] }
10// John
11person.sayName();Diagram Loading...
If the function is assigned to a variable, this refers to the global object. (since its not part of the object anymore)
1const { sayName } = person;
2
3// window
4// undefined
5sayName();Diagram Loading...
1const person = {
2 name: 'John',
3 sayName: function() {
4 console.log(this);
5 console.log(this.name);
6 }
7}
8
9// { name: 'John', sayName: [Function: sayName] }
10// John
11person.sayName();1const { sayName } = person;
2
3// window
4// undefined
5sayName();When used inside a constructor function, this refers to the instance of the object being created.
1class Person {
2 name = 'John';
3
4 constructor(name) {
5 this.name = name;
6 }
7
8 getName() {
9 console.log(this);
10 return this.name;
11 }
12}
13
14const person = new Person('Jane');
15
16// { name: 'Jane', getName: [Function: getName] }
17console.log(person.getName()); // Jane
18Diagram Loading...
However, if the class function is assigned to a variable, this refers to undefined, as it is not part of the class anymore.
const { getName } = person;
getName(); // undefinedDiagram Loading...
JS executes classes in strict mode by default (mandated). This explains the difference in behavior between the "Function extracted from objects" and "Function extracted from classes" examples.
If the method is a static method, this refers to the constructor function (class) itself.
class Person {
value = 10;
static getValue() {
console.log(this); // [Function: Person]
return this.value; // undefined
}
}
console.log(Person.getValue()); // undefined1class Person {
2 name = 'John';
3
4 constructor(name) {
5 this.name = name;
6 }
7
8 getName() {
9 console.log(this);
10 return this.name;
11 }
12}
13
14const person = new Person('Jane');
15
16// { name: 'Jane', getName: [Function: getName] }
17console.log(person.getName()); // Jane
181 const { getName } = person;
2getName(); // undefined1class Person {
2 value = 10;
3
4 static getValue() {
5 console.log(this); // [Function: Person]
6 return this.value; // undefined
7 }
8}
9
10console.log(Person.getValue()); // undefinedWhen used in a function constructor, this refers to the instance of the object being created.
1function Person(name) {
2 this.name = name;
3 this.getName = function() {
4 return this.name;
5 }
6}
7
8const person = new Person('John');
9person.getName(); // JohnDon't forget to use the new keyword when creating a new instance of the object. Forgetting to use the new keyword will result in global object pollution.
1const person = Person('John');
2console.log(person); // undefined
3
4// global object pollution
5// console.log(window.name); if you are using a browser
6console.log(globalThis.name); // John1function Person(name) {
2 this.name = name;
3 this.getName = function() {
4 return this.name;
5 }
6}
7
8const person = new Person('John');
9person.getName(); // John1const person = Person('John');
2console.log(person); // undefined
3
4// global object pollution
5// console.log(window.name); if you are using a browser
6console.log(globalThis.name); // JohnWhen used as an event handler, this refers to the element that triggered the event.
1document.body.addEventListener('click', function () {
2 console.log(this); // <body>
3});Diagram Loading...
1document.body.addEventListener('click', function () {
2 console.log(this); // <body>
3});When used as a callback function for a timer, this refers to the Timer object.
1setTimeout(function() {
2 console.log(this); // Timeout object
3});1setTimeout(function() {
2 console.log(this); // Timeout object
3});1const john = {
2 name: 'John',
3 sayName: function(arg1, arg2) {
4 console.log(this.name);
5 console.log({ arg1, arg2 });
6 }
7}
8
9const jane = {
10 name: 'Jane',
11};If you want to explicitly set the value of this, you can use the following methods:
Executes a function with the execution context of another object.
john.sayName.call(jane, 'value1', 'value2');
// Jane { arg1: 'value1', arg2: 'value2' }Here sayHello() function is executed with the context of jane, instead of john.
Diagram Loading...
Similar to call(), but takes an array of arguments.
john.sayName.apply(jane, ['value1', 'value2']);
// Jane { arg1: 'value1', arg2: 'value2' }Creates a new bounded function that, when called, has its this keyword set to the provided value.
const boundFunction = john.sayName.bind(jane, 'value1', 'value2');
boundedFunction();
// Jane { arg1: 'value1', arg2: 'value2' }1const john = {
2 name: 'John',
3 sayName: function(arg1, arg2) {
4 console.log(this.name);
5 console.log({ arg1, arg2 });
6 }
7}
8
9const jane = {
10 name: 'Jane',
11};Executes a function with the execution context of another object.
1john.sayName.call(jane, 'value1', 'value2');
2// Jane { arg1: 'value1', arg2: 'value2' }Here sayHello() function is executed with the context of jane, instead of john.
Diagram Loading...
1john.sayName.call(jane, 'value1', 'value2');
2// Jane { arg1: 'value1', arg2: 'value2' }Similar to call(), but takes an array of arguments.
1john.sayName.apply(jane, ['value1', 'value2']);
2// Jane { arg1: 'value1', arg2: 'value2' }1john.sayName.apply(jane, ['value1', 'value2']);
2// Jane { arg1: 'value1', arg2: 'value2' }Creates a new bounded function that, when called, has its this keyword set to the provided value.
1const boundFunction = john.sayName.bind(jane, 'value1', 'value2');
2boundedFunction();
3// Jane { arg1: 'value1', arg2: 'value2' }1const boundFunction = john.sayName.bind(jane, 'value1', 'value2');
2boundedFunction();
3// Jane { arg1: 'value1', arg2: 'value2' }Javascript Arrow functions do not have their own this value. Instead, they inherit the this value from the enclosing lexical context.
Diagram Loading...
Object literals do not create a new lexical scope. The this value in this case refers to the scope in which the object was declared.
1const person = {
2 name: 'John',
3 sayName: function() {
4 console.log(this);
5 console.log(this.name);
6 }
7}
8
9// { name: 'John', sayName: [Function: sayName] }
10// John
11person.sayName();class Person {
name = 'John';
constructor(name) {
this.name = name;
}
getName() {
return this?.name;
}
getNameArrow = () => {
return this?.name;
};
}
const person = new Person('Jane');function Person(name) {
this.name = name;
this.getName = function() {
return this.name;
}
this.getNameArrow = () => {
return this.name;
}
}
const person = new Person('John');When getName() and getNameArrow() function are called using the person instance. They both have the same value of this.
getName() - gets the this value from the person instance due to object context.getNameArrow() - gets the this value from the lexical context of the arrow function.person.getName(); // John
person.getNameArrow(); // JohnWhen getName() is called after being assigned to a variable, it loses its object context and this refers to the global object.
const { getName, getNameArrow } = person;
getName(); // undefined
getNameArrow(); // JohnObject literals do not create a new lexical scope. The this value in this case refers to the scope in which the object was declared.
1const person = {
2 name: 'John',
3 sayName: function() {
4 console.log(this);
5 console.log(this.name);
6 }
7}
8
9// { name: 'John', sayName: [Function: sayName] }
10// John
11person.sayName();1const person = {
2 name: 'John',
3 sayName: function() {
4 console.log(this);
5 console.log(this.name);
6 }
7}
8
9// { name: 'John', sayName: [Function: sayName] }
10// John
11person.sayName();1class Person {
2 name = 'John';
3
4 constructor(name) {
5 this.name = name;
6 }
7
8 getName() {
9 return this?.name;
10 }
11
12 getNameArrow = () => {
13 return this?.name;
14 };
15}
16
17const person = new Person('Jane');function Person(name) {
this.name = name;
this.getName = function() {
return this.name;
}
this.getNameArrow = () => {
return this.name;
}
}
const person = new Person('John');When getName() and getNameArrow() function are called using the person instance. They both have the same value of this.
getName() - gets the this value from the person instance due to object context.getNameArrow() - gets the this value from the lexical context of the arrow function.person.getName(); // John
person.getNameArrow(); // JohnWhen getName() is called after being assigned to a variable, it loses its object context and this refers to the global object.
const { getName, getNameArrow } = person;
getName(); // undefined
getNameArrow(); // John1class Person {
2 name = 'John';
3
4 constructor(name) {
5 this.name = name;
6 }
7
8 getName() {
9 return this?.name;
10 }
11
12 getNameArrow = () => {
13 return this?.name;
14 };
15}
16
17const person = new Person('Jane');1function Person(name) {
2 this.name = name;
3
4 this.getName = function() {
5 return this.name;
6 }
7
8 this.getNameArrow = () => {
9 return this.name;
10 }
11}
12
13const person = new Person('John');1person.getName(); // John
2person.getNameArrow(); // John1const { getName, getNameArrow } = person;
2getName(); // undefined
3getNameArrow(); // JohnUnderstanding the 'this' keyword is crucial for writing maintainable and bug-free code in JavaScript. It is a complex topic that requires practice to master.
By using arrow functions and explicit binding, you can avoid the confusion and pitfalls associated with the 'this' keyword.
1console.log(this); // window
2
3console.log(this === window); // true
41'use strict';
2
3console.log(this); // undefined
4
5console.log(this === window); // falseWhen used inside a function, this refers to the object that called the function.
1const getThis = function() {
2 console.log(this);
3}
4
5// window, since getThis is called in the global context
6getThis();Diagram Loading...
1const getThis = function() {
2 console.log(this);
3}
4
5// window, since getThis is called in the global context
6getThis();When function is a property of an object, this refers to the object itself.
1const person = {
2 name: 'John',
3 sayName: function() {
4 console.log(this);
5 console.log(this.name);
6 }
7}
8
9// { name: 'John', sayName: [Function: sayName] }
10// John
11person.sayName();Diagram Loading...
If the function is assigned to a variable, this refers to the global object. (since its not part of the object anymore)
1const { sayName } = person;
2
3// window
4// undefined
5sayName();Diagram Loading...
1const person = {
2 name: 'John',
3 sayName: function() {
4 console.log(this);
5 console.log(this.name);
6 }
7}
8
9// { name: 'John', sayName: [Function: sayName] }
10// John
11person.sayName();1const { sayName } = person;
2
3// window
4// undefined
5sayName();When used inside a constructor function, this refers to the instance of the object being created.
1class Person {
2 name = 'John';
3
4 constructor(name) {
5 this.name = name;
6 }
7
8 getName() {
9 console.log(this);
10 return this.name;
11 }
12}
13
14const person = new Person('Jane');
15
16// { name: 'Jane', getName: [Function: getName] }
17console.log(person.getName()); // Jane
18Diagram Loading...
However, if the class function is assigned to a variable, this refers to undefined, as it is not part of the class anymore.
const { getName } = person;
getName(); // undefinedDiagram Loading...
JS executes classes in strict mode by default (mandated). This explains the difference in behavior between the "Function extracted from objects" and "Function extracted from classes" examples.
If the method is a static method, this refers to the constructor function (class) itself.
class Person {
value = 10;
static getValue() {
console.log(this); // [Function: Person]
return this.value; // undefined
}
}
console.log(Person.getValue()); // undefined1class Person {
2 name = 'John';
3
4 constructor(name) {
5 this.name = name;
6 }
7
8 getName() {
9 console.log(this);
10 return this.name;
11 }
12}
13
14const person = new Person('Jane');
15
16// { name: 'Jane', getName: [Function: getName] }
17console.log(person.getName()); // Jane
181 const { getName } = person;
2getName(); // undefined1class Person {
2 value = 10;
3
4 static getValue() {
5 console.log(this); // [Function: Person]
6 return this.value; // undefined
7 }
8}
9
10console.log(Person.getValue()); // undefinedWhen used in a function constructor, this refers to the instance of the object being created.
1function Person(name) {
2 this.name = name;
3 this.getName = function() {
4 return this.name;
5 }
6}
7
8const person = new Person('John');
9person.getName(); // JohnDon't forget to use the new keyword when creating a new instance of the object. Forgetting to use the new keyword will result in global object pollution.
1const person = Person('John');
2console.log(person); // undefined
3
4// global object pollution
5// console.log(window.name); if you are using a browser
6console.log(globalThis.name); // John1function Person(name) {
2 this.name = name;
3 this.getName = function() {
4 return this.name;
5 }
6}
7
8const person = new Person('John');
9person.getName(); // John1const person = Person('John');
2console.log(person); // undefined
3
4// global object pollution
5// console.log(window.name); if you are using a browser
6console.log(globalThis.name); // JohnWhen used as an event handler, this refers to the element that triggered the event.
1document.body.addEventListener('click', function () {
2 console.log(this); // <body>
3});Diagram Loading...
1document.body.addEventListener('click', function () {
2 console.log(this); // <body>
3});When used as a callback function for a timer, this refers to the Timer object.
1setTimeout(function() {
2 console.log(this); // Timeout object
3});1setTimeout(function() {
2 console.log(this); // Timeout object
3});1 const { getName } = person;
2getName(); // undefined1class Person {
2 value = 10;
3
4 static getValue() {
5 console.log(this); // [Function: Person]
6 return this.value; // undefined
7 }
8}
9
10console.log(Person.getValue()); // undefined1john.sayName.call(jane, 'value1', 'value2');
2// Jane { arg1: 'value1', arg2: 'value2' }1john.sayName.apply(jane, ['value1', 'value2']);
2// Jane { arg1: 'value1', arg2: 'value2' }Creates a new bounded function that, when called, has its this keyword set to the provided value.
1const boundFunction = john.sayName.bind(jane, 'value1', 'value2');
2boundedFunction();
3// Jane { arg1: 'value1', arg2: 'value2' }1const boundFunction = john.sayName.bind(jane, 'value1', 'value2');
2boundedFunction();
3// Jane { arg1: 'value1', arg2: 'value2' }1class Person {
2 name = 'John';
3
4 constructor(name) {
5 this.name = name;
6 }
7
8 getName() {
9 return this?.name;
10 }
11
12 getNameArrow = () => {
13 return this?.name;
14 };
15}
16
17const person = new Person('Jane');function Person(name) {
this.name = name;
this.getName = function() {
return this.name;
}
this.getNameArrow = () => {
return this.name;
}
}
const person = new Person('John');When getName() and getNameArrow() function are called using the person instance. They both have the same value of this.
getName() - gets the this value from the person instance due to object context.getNameArrow() - gets the this value from the lexical context of the arrow function.person.getName(); // John
person.getNameArrow(); // JohnWhen getName() is called after being assigned to a variable, it loses its object context and this refers to the global object.
const { getName, getNameArrow } = person;
getName(); // undefined
getNameArrow(); // John1class Person {
2 name = 'John';
3
4 constructor(name) {
5 this.name = name;
6 }
7
8 getName() {
9 return this?.name;
10 }
11
12 getNameArrow = () => {
13 return this?.name;
14 };
15}
16
17const person = new Person('Jane');1function Person(name) {
2 this.name = name;
3
4 this.getName = function() {
5 return this.name;
6 }
7
8 this.getNameArrow = () => {
9 return this.name;
10 }
11}
12
13const person = new Person('John');1person.getName(); // John
2person.getNameArrow(); // John1const { getName, getNameArrow } = person;
2getName(); // undefined
3getNameArrow(); // John1function Person(name) {
2 this.name = name;
3
4 this.getName = function() {
5 return this.name;
6 }
7
8 this.getNameArrow = () => {
9 return this.name;
10 }
11}
12
13const person = new Person('John');1person.getName(); // John
2person.getNameArrow(); // John1const { getName, getNameArrow } = person;
2getName(); // undefined
3getNameArrow(); // John1console.log(this); // window
2
3console.log(this === window); // true
41'use strict';
2
3console.log(this); // undefined
4
5console.log(this === window); // falseWhen used inside a function, this refers to the object that called the function.
1const getThis = function() {
2 console.log(this);
3}
4
5// window, since getThis is called in the global context
6getThis();Diagram Loading...
1const getThis = function() {
2 console.log(this);
3}
4
5// window, since getThis is called in the global context
6getThis();When function is a property of an object, this refers to the object itself.
1const person = {
2 name: 'John',
3 sayName: function() {
4 console.log(this);
5 console.log(this.name);
6 }
7}
8
9// { name: 'John', sayName: [Function: sayName] }
10// John
11person.sayName();Diagram Loading...
If the function is assigned to a variable, this refers to the global object. (since its not part of the object anymore)
1const { sayName } = person;
2
3// window
4// undefined
5sayName();Diagram Loading...
1const person = {
2 name: 'John',
3 sayName: function() {
4 console.log(this);
5 console.log(this.name);
6 }
7}
8
9// { name: 'John', sayName: [Function: sayName] }
10// John
11person.sayName();1const { sayName } = person;
2
3// window
4// undefined
5sayName();When used inside a constructor function, this refers to the instance of the object being created.
1class Person {
2 name = 'John';
3
4 constructor(name) {
5 this.name = name;
6 }
7
8 getName() {
9 console.log(this);
10 return this.name;
11 }
12}
13
14const person = new Person('Jane');
15
16// { name: 'Jane', getName: [Function: getName] }
17console.log(person.getName()); // Jane
18Diagram Loading...
However, if the class function is assigned to a variable, this refers to undefined, as it is not part of the class anymore.
const { getName } = person;
getName(); // undefinedDiagram Loading...
JS executes classes in strict mode by default (mandated). This explains the difference in behavior between the "Function extracted from objects" and "Function extracted from classes" examples.
If the method is a static method, this refers to the constructor function (class) itself.
class Person {
value = 10;
static getValue() {
console.log(this); // [Function: Person]
return this.value; // undefined
}
}
console.log(Person.getValue()); // undefined1class Person {
2 name = 'John';
3
4 constructor(name) {
5 this.name = name;
6 }
7
8 getName() {
9 console.log(this);
10 return this.name;
11 }
12}
13
14const person = new Person('Jane');
15
16// { name: 'Jane', getName: [Function: getName] }
17console.log(person.getName()); // Jane
181 const { getName } = person;
2getName(); // undefined1class Person {
2 value = 10;
3
4 static getValue() {
5 console.log(this); // [Function: Person]
6 return this.value; // undefined
7 }
8}
9
10console.log(Person.getValue()); // undefinedWhen used in a function constructor, this refers to the instance of the object being created.
1function Person(name) {
2 this.name = name;
3 this.getName = function() {
4 return this.name;
5 }
6}
7
8const person = new Person('John');
9person.getName(); // JohnDon't forget to use the new keyword when creating a new instance of the object. Forgetting to use the new keyword will result in global object pollution.
1const person = Person('John');
2console.log(person); // undefined
3
4// global object pollution
5// console.log(window.name); if you are using a browser
6console.log(globalThis.name); // John1function Person(name) {
2 this.name = name;
3 this.getName = function() {
4 return this.name;
5 }
6}
7
8const person = new Person('John');
9person.getName(); // John1const person = Person('John');
2console.log(person); // undefined
3
4// global object pollution
5// console.log(window.name); if you are using a browser
6console.log(globalThis.name); // JohnWhen used as an event handler, this refers to the element that triggered the event.
1document.body.addEventListener('click', function () {
2 console.log(this); // <body>
3});Diagram Loading...
1document.body.addEventListener('click', function () {
2 console.log(this); // <body>
3});When used as a callback function for a timer, this refers to the Timer object.
1setTimeout(function() {
2 console.log(this); // Timeout object
3});1setTimeout(function() {
2 console.log(this); // Timeout object
3});1 const { getName } = person;
2getName(); // undefined1class Person {
2 value = 10;
3
4 static getValue() {
5 console.log(this); // [Function: Person]
6 return this.value; // undefined
7 }
8}
9
10console.log(Person.getValue()); // undefined1john.sayName.call(jane, 'value1', 'value2');
2// Jane { arg1: 'value1', arg2: 'value2' }1john.sayName.apply(jane, ['value1', 'value2']);
2// Jane { arg1: 'value1', arg2: 'value2' }Creates a new bounded function that, when called, has its this keyword set to the provided value.
1const boundFunction = john.sayName.bind(jane, 'value1', 'value2');
2boundedFunction();
3// Jane { arg1: 'value1', arg2: 'value2' }1const boundFunction = john.sayName.bind(jane, 'value1', 'value2');
2boundedFunction();
3// Jane { arg1: 'value1', arg2: 'value2' }1class Person {
2 name = 'John';
3
4 constructor(name) {
5 this.name = name;
6 }
7
8 getName() {
9 return this?.name;
10 }
11
12 getNameArrow = () => {
13 return this?.name;
14 };
15}
16
17const person = new Person('Jane');function Person(name) {
this.name = name;
this.getName = function() {
return this.name;
}
this.getNameArrow = () => {
return this.name;
}
}
const person = new Person('John');When getName() and getNameArrow() function are called using the person instance. They both have the same value of this.
getName() - gets the this value from the person instance due to object context.getNameArrow() - gets the this value from the lexical context of the arrow function.person.getName(); // John
person.getNameArrow(); // JohnWhen getName() is called after being assigned to a variable, it loses its object context and this refers to the global object.
const { getName, getNameArrow } = person;
getName(); // undefined
getNameArrow(); // John1class Person {
2 name = 'John';
3
4 constructor(name) {
5 this.name = name;
6 }
7
8 getName() {
9 return this?.name;
10 }
11
12 getNameArrow = () => {
13 return this?.name;
14 };
15}
16
17const person = new Person('Jane');1function Person(name) {
2 this.name = name;
3
4 this.getName = function() {
5 return this.name;
6 }
7
8 this.getNameArrow = () => {
9 return this.name;
10 }
11}
12
13const person = new Person('John');1person.getName(); // John
2person.getNameArrow(); // John1const { getName, getNameArrow } = person;
2getName(); // undefined
3getNameArrow(); // John1function Person(name) {
2 this.name = name;
3
4 this.getName = function() {
5 return this.name;
6 }
7
8 this.getNameArrow = () => {
9 return this.name;
10 }
11}
12
13const person = new Person('John');1person.getName(); // John
2person.getNameArrow(); // John1const { getName, getNameArrow } = person;
2getName(); // undefined
3getNameArrow(); // John1 const { getName } = person;
2getName(); // undefined1class Person {
2 value = 10;
3
4 static getValue() {
5 console.log(this); // [Function: Person]
6 return this.value; // undefined
7 }
8}
9
10console.log(Person.getValue()); // undefined1function Person(name) {
2 this.name = name;
3
4 this.getName = function() {
5 return this.name;
6 }
7
8 this.getNameArrow = () => {
9 return this.name;
10 }
11}
12
13const person = new Person('John');1person.getName(); // John
2person.getNameArrow(); // John1const { getName, getNameArrow } = person;
2getName(); // undefined
3getNameArrow(); // John1 const { getName } = person;
2getName(); // undefined1class Person {
2 value = 10;
3
4 static getValue() {
5 console.log(this); // [Function: Person]
6 return this.value; // undefined
7 }
8}
9
10console.log(Person.getValue()); // undefined1function Person(name) {
2 this.name = name;
3
4 this.getName = function() {
5 return this.name;
6 }
7
8 this.getNameArrow = () => {
9 return this.name;
10 }
11}
12
13const person = new Person('John');1person.getName(); // John
2person.getNameArrow(); // John1const { getName, getNameArrow } = person;
2getName(); // undefined
3getNameArrow(); // John