Mastering JavaScript Functional Programming
上QQ阅读APP看书,第一时间看更新

Handling the this value

A classic problem with JS is the handling of this -- whose value isn't always what you expect it to be. ES2015 solved this with arrow functions, which inherit the proper this value, so problems are avoided. To see an example of the possible problems, in the following code, by the time the timeout function is called, this will point to the global (window) variable instead of the new object, so you'll get an undefined in the console:

function ShowItself1(identity) {
this.identity = identity;
setTimeout(function() {
console.log(this.identity);
}, 1000);
}

var x = new ShowItself1("Functional");
// after one second, undefined is displayed

There are two classic ways of solving this with old-fashioned JS5, plus the arrow way of working:

  • One solution uses a closure, and defines a local variable (usually  named that or sometimes self), which will get the original value of this so it won't be undefined
  • The second way uses .bind(), so the timeout function will be bound to the correct value of this
  • And the third, more modern way, just uses an arrow function, so this gets the correct value (pointing to the object) without further ado

We will also be using .bind().  See the Of lambdas and etas section.

Let's see the three solutions in actual code:

function ShowItself2(identity) {
this.identity = identity;
let that = this;
setTimeout(function() {
console.log(that.identity);
}, 1000);

setTimeout(
function() {
console.log(this.identity);
}.bind(this),
2000
);

setTimeout(() => {
console.log(this.identity);
}, 3000);
}

var x = new ShowItself2("JavaScript");
// after one second, "JavaScript"
// after another second, the same
// after yet another second, once again