this Javascript
In Javascript, it refers to the execution context.
Inside a function, it refers to the global object (window) or undefined
in strict mode
function anyFunction() {
console.log(this)
}
anyFunction()
/*
{ console: [Getter],
...
setTimeout: { [Function: setTimeout] [Symbol(util.promisify.custom)]: [Function] } }
*/
In strict mode, it's undefined for safety
'use strict'
function anyFunction() {
console.log(this)
}
anyFunction() // undefined
this in a nested function
When there is a nested function, it gets confusing
let numbers = {
a: 1,
b: 2,
sum: function () {
// `this` -> numbers
console.log(this === numbers) // true
function calculate() {
// `this` -> window or undefined
return this.a + this.b
}
return calculate()
},
}
let ret = numbers.sum()
console.log(ret) // NaN
When it's nested, its execution context is actually in global scope.
In order to fix the problem,
let numbers = {
a: 1,
b: 2,
sum: function () {
// `this` -> numbers
console.log(this === numbers) // true
function calculate() {
// `this` -> window or undefined
return this.a + this.b
}
// execute calculate with `this` context given
return calculate.call(this)
},
}
let ret = numbers.sum()
console.log(ret) // => 3
this in a isolated method
It is easy to mess up this
with a class method especially when it's isolated. For example setTimeout(class.method, 0)
function Animal(type, name) {
this.type = type
this.name = name
this.logInfo = function () {
console.log(`[${this.type}] ${this.name}`)
}
}
let myDog = new Animal('dog', 'puppy')
setTimeout(myDog.logInfo, 0) // [undefined] undefined
You might have expected it would be "[dog] puppy" but it's not. When it goes to setTimeout, the method becomes isolated from the class. It's acting like a global function
To fix this problem, one might bind this
function Animal(type, name) {
this.type = type
this.name = name
this.logInfo = function () {
console.log(`[${this.type}] ${this.name}`)
}
}
let myDog = new Animal('dog', 'puppy')
setTimeout(myDog.logInfo.bind(myDog), 0) // [dog] puppy
this in constructor
It is the most intuitive case. When this
is used inside a class constructor. It refers to a new instance that will be created.
class Animal {
constructor(type, name) {
// this refers to a new object to be created
this.name = name
this.type = type
}
logInfo() {
let message = `[${this.type}] ${this.name}`
console.log(message)
}
}
let myDog = new Animal('dog', 'puppy')
myDog.logInfo() // [dog] puppy
The only time it can go wrong is probably when you miss new
keyword
class Animal {
constructor(type, name) {
// this refers to a new object to be created
this.name = name
this.type = type
}
logInfo() {
let message = `[${this.type}] ${this.name}`
console.log(message)
}
}
// illegal
// let myDog = Animal("dog", "puppy");
// myDog.logInfo();