How to Determine this
To determine this
, you need to learn only one rule: the context value inside a
function (not arrow) is determined not at the time of its creation, but at
the time of calling. That is, the value of this
is determined by how the
function is called, not where it was declared.
this
in the global scope
In the global scope, if the script is not executed in strict mode, this
refers
to the window
object. In strict mode the value of this
in the global scope
will be undefined
.
function foo() {
console.log(this);
}
foo(); // window without "use strict" and undefined with "use strict"
this
in object method
If a function is called as an object method, the context will refer to the object that includes the method.
const petya = {
username: "Petya",
showThis() {
console.log(this);
},
showName() {
console.log(this.username);
},
};
petya.showThis(); // {username: "Petya", showThis: ƒ, showName: ƒ}
petya.showName(); // 'Petya'
Let's look at a more complex example for better understanding.
- First, create a function in the global scope and call it.
- Then assign it to an object property and invoke it as a method of this object.
function showThis() {
console.log("this in showThis: ", this);
}
// Calling in the global context
showThis(); // this in showThis: Window
const user = {
username: "Mango",
};
// Writing a reference to the function to the object property
// Note that this is not a call because it has no ()
user.showContext = showThis;
// Calling the function in the object context
// this will point to the current object that serves as the
// call context, not to the global object.
user.showContext(); // this in showThis: {username: "Mango", showContext: ƒ}
this
in callback functions
When passing object methods as callback functions, the context is not preserved. A callback is a method reference that is assigned as the value of a parameter called without an object.
const customer = {
firstName: "Jacob",
lastName: "Mercer",
getFullName() {
return `${this.firstName} ${this.lastName}`;
},
};
function makeMessage(callback) {
// callback() is a call of the getFullName method without an object
console.log(`Processing request from ${callback()}.`);
}
makeMessage(customer.getFullName); // Function call error
The solution to this problem is discussed in the section on bind() method and object methods.
this
in arrow functions
Arrow functions do not have their own this
. Unlike with regular functions, you
cannot change the value of this
inside an arrow after its declaration.
The context inside an arrow is determined by the place of its declaration, not the call, and refers to the parent function’s context.
Arrow functions also ignore the presence of strict mode. If the arrow remembers
the global context, this
in it will contain a reference to window
,
regardless of whether the script is executed in strict mode or not.
const showThis = () => {
console.log("this in showThis: ", this);
};
showThis(); // this in showThis: window
const user = {
username: "Mango",
};
user.showContext = showThis;
user.showContext(); // this in showThis: window
By limiting arrow functions to a constant context, JavaScript engines can better
optimize them, unlike regular functions whose this
value can be changed.
The example is not practical, but it shows well how the context for arrows works. The context value is taken from the parent scope.
const hotel = {
username: "Resort hotel",
showThis() {
const foo = () => {
// Arrows remember the context during declaration,
// from the parent scope
console.log("this in foo: ", this);
};
foo();
console.log("this in showThis: ", this);
},
};
hotel.showThis();
// this in foo: {username: 'Resort hotel', showThis: ƒ}
// this in showThis: {username: 'Resort hotel',showThis: ƒ}