The Keyword "this"
Right off the bat, here are the key rules behind the this
keyword in
JavaScript:
this
is an expression that serves as a reference to some environment.- The value of
this
is determined at runtime. - The default value of
this
is the global object. - When an object method is called, the
this
keyword refers to the object the method was called on. - In strict mode, if a function's body uses the
this
keyword, thethis
is undefined until the function is called. - In an arrow function, the value of
this
is the value ofthis
in the arrow function's enclosing context. - In a constructor call,
this
refers to the object being constructed. - In an event handler,
this
refers 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).