Last Updated on April 3, 2016
When a function is set and the this
value is not assigned, it is always the window object. It can change depending on where the function is invoked.
console.log(this); // Window
function f1() {
console.log(this); // Window
}
f1();
var f2 = function() {
console.log(this); // Window
}
The quirk is, why does javascript set the this
value of a function, within a function within an object to the window object?
var o = {
name: "Peter",
myFunc: function() {
this.name = "John";
console.log(this);
var setname = function(newname) {
this.name = newname;
}
setname("Updated to Jim");
console.log(this); // Not changed
},
}
o.myFunc();
How do we deal with it? The self pattern: var self = this;
But before that let’s look at what a function contains.
- A function contains properties:
- name property (can be anonymous)
- code property (invocalble “( )”
- Every function also contains three special methods
- call
- bind
- apply
Here is an example of the self
pattern.
var o = {
name: "Peter",
myFunc: function() {
var self = this; // The magic line
self.name = "John";
console.log(self);
var setname = function(newname) {
self.name = newname;
}
setname("Updated to Jim");
console.log(self); // Without the self pattern this would remain "John"
},
}
o.myFunc();
.bind
, .call()
and .apply()
are accessed by using the dot notation.
.bind
creates a copy of the function you are calling, and passes the object you want to be the this
property.
var car = {
make: "Honda",
model: "Pilot",
year: "2013",
carInfo: function() {
var info = this.year + ", " + this.make + " " + this.model;
return info;
}
}
var displayInfo = function(color, weight) {
console.log("The info is: " + this.carInfo() + " " + color + " " + weight);
}
var showCarInfo = displayInfo.bind(car);
showCarInfo();
//-------------------------
displayInfo.call(car, "white", "10,000 lbs");
displayInfo.apply(car, ["white", "10,000 lbs"]);
With .call() and apply()
you are not making a copy – you are invoking the function directly and passing it’s this
property with parameters – .apply()
requires an array of parameters and .call()
requires a list.
Since .bind()
is creating a copy of the function, you have some useful patterns at your disposal – function borrowing, and function currying.
//-------------------------
// Function Borrowing
var car2 = {
make: "Chevy",
model: "Traverse",
year: "2016",
}
console.log(car.carInfo.apply(car2) );
//-------------------------
// Function Currying
function multiply(a,b) {
return a*b;
}
var multiplyByTwo = multiply.bind(this, 2);
console.log( multiplyByTwo(4) );
var multiplyByThree = multiply.bind(this, 3);
console.log( multiplyByThree(4) );