The Keyword "this"
Right off the bat, here are the key rules behind the this keyword in
JavaScript:
thisis an expression that serves as a reference to some environment.- The value of
thisis determined at runtime. - The default value of
thisis the global object. - When an object method is called, the
thiskeyword refers to the object the method was called on. - In strict mode, if a function's body uses the
thiskeyword, thethisis undefined until the function is called. - In an arrow function, the value of
thisis the value ofthisin the arrow function's enclosing context. - In a constructor call,
thisrefers to the object being constructed. - In an event handler,
thisrefers to the element the event listener is attached to.
A variable declared with var in the global scope will be included in the
window object as a property. But, variables declared with let and
const will not be included. The this keyword is a keyword that
references the current execution scope, and gives an object back as its
output. Thus, the returned object changes depending on the current
execution's scope. The execution might have a global scope, or it might
have some other scope—expression scope, block scope, function scope, etc.
For example, consider the code below:
function helloWorld() {
console.log("Hi");
console.log(this);
}
helloWorld();
Window {
window: Window,
self: Window,
document: document,
name: "",
location: Location,
…
}
In the code above, our function contains the statement,
console.log(this);. This statement says, "JavaScript, display in the
console this function's scope." In doing so, we get back an object called
the Window. The window is the global scope in the browser. When we wrote
the function helloworld, we wrote directly into the program, not under
any other block. When we write functions like this, the functions are
written in the global scope. When a function is written in the global
scope, it becomes a property in the global scope object (in this case, the
browser's global scope), and as such, we can call it with the usual object
syntax: window.functionName(). The same goes for variables declared with
var directly into the program (not inside any other block scope).
var vector = 3;
By declaring the variable vector with the keyword var above, the name
vector now becomes a property of the Window object, which we can call
with window.vector. But, this rule does not apply to variables declared
with the keywords let and const.
Why is 'this' so useful?
Consider the code below, where we write a function using the this keyword
inside an object:
// An object containing the properties of tree ferns
const treeFern = {
scientificName: "Dicksonia antarctica",
genus: "Dicksonia",
family: "Dicksoniaceae",
Order: "Cyatheales",
Class: "Polypodiopsida",
Division: "Polypodiophyta",
Kingdom: "Plantae",
allDetails() {
console.log(this);
},
};
treeFern.allDetails();
{
scientificName: 'Dicksonia antarctica',
genus: 'Dicksonia',
family: 'Dicksoniaceae',
Order: 'Cyatheales',
Class: 'Polypodiopsida',
Division: 'Polypodiophyta',
Kingdom: 'Plantae',
allDetails: [Function: allDetails]
}
In the example above, we wrote the function allDetails() inside the
object treeFern. That function contains the statement
console.log(this);, which tells JavaScript, "Display in the console this
function's scope." When we call the function with object syntax,
treeFern.allDetails(), we get back that the entire scope of that
function, the object treefern.
An astute observer might notice the immediate utility of the this
keyword: It allows us to use the properties inside an object while writing
statements inside said object.
// Here is an object of some mathematical functions:
const mathematician = {
firstName: "Renee",
lastName: "Descartes",
firstNameDisplay() {
console.log(this.firstName);
},
};
mathematician.firstNameDisplay();
Renee
A more elaborate example:
const RD = {
firstName: "Renee",
lastName: "Descartes",
notable: "Cartesian plane",
details() {
console.log(
`${this.firstName} ${this.lastName}, notable for the ${this.notable}.`,
);
},
};
RD.details();
Renee Descartes, notable for the Cartesian plane.
Using Destructuring Syntax with 'this'
In the example above, we constantly had to write the this keyword. We can
cut all of that out with the destructuring syntax:
const rD = {
firstName: "Renee",
lastName: "Descartes",
notable: "Cartesian plane",
details() {
const { firstName, lastName, notable } = this;
console.log(`${firstName} ${lastName}, notable for the ${notable}.`);
},
};
rD.details(); // Output: Renee Descartes, notable for the Cartesian plane.
The this keyword allows us to write methods that can "see" the other
properties inside the object.
Using the 'this' Keyword to Reference Methods
We can use this to reference other methods inside an object:
const sR = {
first: "Srinivasa",
last: "Ramanujan",
country: "India",
fullName() {
return `${this.first} ${this.last}`
},
summary() {
const fullName = this.fullName();
return `${fullName} is a mathematician from ${this.country}.`
}
};
console.log(sR.summary());
```bash
Srinivasa Ramanujan is a mathematician from India
The Value of 'This'
The value of the this keyword depends on how we invoke the function that
uses it. Put simply, the value of the this keyword depends on where we
write it and how we write it. To see this crucial point, consider the
code below:
// Same object from the preceding example.
const sR = {
first: "Srinivasa",
last: "Ramanujan",
country: "India",
fullName() {
return `${this.first} ${this.last}`;
},
summary() {
const fullName = this.fullName();
return `${fullName} is mathematician from ${this.country}.`;
},
};
Suppose we assign the method SR.summary() to a variable:
const summary = sR.summary;
Now suppose we call that function:
console.log(summary());
TypeError: this.fullName is not a function
Compare the error above with the following code:
// Same object from the preceding example.
const sR = {
first: "Srinivasa",
last: "Ramanujan",
country: "India",
fullName() {
return `${this.first} ${this.last}`;
},
summary() {
console.log(this); // Let's see what the object is
const fullName = this.fullName();
return `${fullName} is mathematician from ${this.country}.`;
},
};
const summary = sR.summary;
console.log(summary());
Window {window: Window, self: Window, document: document, name: "", location: Location, …}
Uncaught TypeError: this.fullName is not a function at summary
In the second example, we see that this is referencing the object
window, the browser's global scope. If we instead just used the typical
object key syntax rather than the variable:
// Same object from the preceding example.
const sR = {
first: "Srinivasa",
last: "Ramanujan",
country: "India",
fullName() {
return `${this.first} ${this.last}`;
},
summary() {
console.log(this);
const fullName = this.fullName();
return `${fullName} is mathematician from ${this.country}.`;
},
};
console.log(sR.summary());
Output:
{first: "Srinivasa", last: "Ramanujan", country: "India", fullName: Ć’, summary: Ć’}
Srinivasa Ramanujan is mathematician from India.
Now we see that the value of this is the object it's contained in, sR,
rather than the window object, the global scope.This shows that the value
of this is determined by the way we invoke the function that uses the
this keyword. One way to think about this: When we explicitly call the
function with the object syntax, object.function, the value of this is
the object itself. But, when we simply just call the function without
explicitly stating the object, the value of this is the global scope
object (which, in the browser, is the window object).