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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
//------------------------- // 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) ); |