Introduction
Hi, I'm Elie!
The keyword 'this'
Objectives
- Define what the keyword 'this' is
- Understand the four ways to always figure out what the keyword 'this' is
- Try as hard as possible not to use the word "this" in a sentence
So what is 'this'?
- A reserved keyword in JavaScript
- Usually determined by how a function is called (what we call 'execution context')
- Can be determined using four rules (global, object/implicit, explicit, new)
1 - Global Context
console.log(this) // window
function whatIsThis(){
return this
}
function variablesInThis(){
// since the value of this is the window
// all we are doing here is creating a global variable
this.person = "Elie"
}
console.log(person) // Elie
whatIsThis() // window
When 'this' is not inside of a declared object
Strict Mode
"use strict"
console.log(this) // window
function whatIsThis(){
return this
}
function variablesInThis(){
// since we are in strict mode this is undefined
// so what happens if we add a property on undefined?
// let's see what happens when we call the function...
this.person = "Elie"
}
variablesInThis() // TypeError, can't set person on undefined!
whatIsThis() // undefined
When we enable strict mode and we are not inside a declared object
2 - Implicit/Object
// strict mode does NOT make a difference here
var person = {
firstName: "Elie",
sayHi: function(){
return "Hi " + this.firstName
},
determineContext: function(){
return this === person
}
}
When the keyword 'this' IS inside of a declared object
person.sayHi() // "Hi Elie"
person.determineContext() // true
Nested Objects
var person = {
firstName: "Colt",
sayHi: function(){
return "Hi " + this.firstName;
},
determineContext: function(){
return this === person;
},
dog: {
sayHello: function(){
return "Hello " + this.firstName;
},
determineContext: function(){
return this === person;
}
}
}
What happens when we have a nested object?
person.sayHi() // "Hi Colt"
person.determineContext() // true
// but what is the value of the keyword this right now?
person.dog.sayHello() // "Hello undefined"
person.dog.determineContext() // false
3 - Explicit Binding
Choose what we want the context of 'this' to be using call, apply or bind
NAME OF METHOD | PARAMETERS | INVOKE IMMEDIATELY? |
---|---|---|
Call | thisArg, a, b, c, d , ... | Yes |
Apply | thisArg, [a,b,c,d, ...] | Yes |
Bind | thisArg, a, b, c, d , ... | No |
Fixing Up With Call
var person = {
firstName: "Colt",
sayHi: function(){
return "Hi " + this.firstName
},
determineContext: function(){
return this === person
},
dog: {
sayHello: function(){
return "Hello " + this.firstName
},
determineContext: function(){
return this === person
}
}
}
person.sayHi() // "Hi Colt"
person.determineContext() // true
person.dog.sayHello.call(person) // "Hello Colt"
person.dog.determineContext.call(person) // true
// Using call worked! Notice that we do NOT invoke sayHello or determineContext
Using Call in the Wild
var colt = {
firstName: "Colt",
sayHi: function(){
return "Hi " + this.firstName
}
}
var elie = {
firstName: "Elie",
// Look at all this duplication :(
sayHi: function(){
return "Hi " + this.firstName
}
}
colt.sayHi() // Hi Colt
elie.sayHi() // Hi Elie (but we had to copy and paste the function from above...)
// How can we refactor the duplication using call?
// How can we "borrow" the sayHi function from colt
// and set the value of 'this' to be elie?
Let's examine a very common use case
Using Call in the Wild
var colt = {
firstName: "Colt",
sayHi: function(){
return "Hi " + this.firstName
}
}
var elie = {
firstName: "Elie"
}
colt.sayHi() // Hi Colt
colt.sayHi.call(elie) // Hi Elie
// much better!
Solution
What about Apply?
var colt = {
firstName: "Colt",
sayHi: function(){
return "Hi " + this.firstName
},
addNumbers: function(a,b,c,d){
return this.firstName + " just calculated " + (a+b+c+d);
}
}
var elie = {
firstName: "Elie"
}
colt.sayHi() // Hi Colt
colt.sayHi.apply(elie) // Hi Elie
// well this seems the same....but what happens when we start adding arguments?
It's almost identical to call - except the parameters!
colt.addNumbers(1,2,3,4) // Colt just calculated 10
colt.addNumbers.call(elie,1,2,3,4) // Elie just calculated 10
colt.addNumbers.apply(elie,[1,2,3,4]) // Elie just calculated 10
// What differences do you see?
And what about bind?
var colt = {
firstName: "Colt",
sayHi: function(){
return "Hi " + this.firstName
},
addNumbers: function(a,b,c,d){
return this.firstName + " just calculated " + (a+b+c+d);
}
}
var elie = {
firstName: "Elie"
}
The parameters work like call, but bind returns a function with the context of 'this' bound already!
var elieCalc = colt.addNumbers.bind(elie,1,2,3,4) // function(){}...
elieCalc() // Elie just calculated 10
// With bind - we do not need to know all the arguments up front!
var elieCalc = colt.addNumbers.bind(elie,1,2) // function(){}...
elieCalc(3,4) // Elie just calculated 10
Bind in the wild
var colt = {
firstName: "Colt",
sayHi: function(){
setTimeout(function(){
console.log("Hi " + this.firstName)
},1000)
}
}
Very commonly we lose the context of 'this', but in functions that we do not want to execute right away!
var colt = {
firstName: "Colt",
sayHi: function(){
setTimeout(function(){
console.log("Hi " + this.firstName)
}.bind(this),1000)
}
}
Use bind to set the correct context of 'this'
colt.sayHi() // Hi undefined (1000 milliseconds later)
colt.sayHi() // Hi Colt (1000 milliseconds later)
4 - The 'new' keyword
function Person(firstName, lastName){
this.firstName = firstName
this.lastName = lastName
}
We can set the context of the keyword 'this' using the 'new' keyword - it does quite a bit more as well which we will discuss further when we talk about OOP
var elie = new Person("Elie", "Schoppik");
elie.firstName // "Elie"
elie.lastName // "Schoppik"
Recap
- The keyword 'this' is a reserved keyword in JavaScript and its value is determined at execution
- It is either set using the global context, object binding, explicit binding, or the new keyword
- When set in the global context in a function, it is either the global object (window if in the browser) or undefined (if we are using strict mode)
- To explicitly set the value of the keyword 'this', we use call, apply, or bind
- We can also use the 'new' keyword to set the context of 'this', which we will discuss when we talk about Object Oriented Programming
The keyword 'this'
By Elie Schoppik
The keyword 'this'
What the keyword 'this' is in JavaScript and how we determine its value
- 2,426