In one of my password toggle scripts, I needed to access an outer function's this
value from within a callback function. Accessing an outer function's scope like this is called a closure, or lexical scoping.
Here's the snippet in question:
function handleChange () {
passwords.forEach(password => {
togglePassword(this, password);
});
}
toggle.addEventListener('change', handleChange);
Arrow functions don't have their own binding for the this
value, so this code does what I want it to do. The this
keyword refers to the parent context, which in this case, is the toggle
variable.
The arrow function saves me from having to use the old var that = this
hack:
function handleChange () {
var that = this;
passwords.forEach(function (password) {
togglePassword(that, password);
});
}
But it's also possible to change the context of the forEach()
callback.
The forEach()
method takes an optional second argument, which is the value to use for the this
keyword inside the callback function:
function handleChange () {
passwords.forEach(function (password) {
togglePassword(this, password);
}, this);
}
In the snippet above, the this
value inside the callback function again references the this
value of the outer function, just like it did with the arrow function.
You could also use the bind()
method to change the context...
function handleChange () {
passwords.forEach(function (password) {
togglePassword(this, password);
}.bind(this));
}
...But you might as well just use the optional second argument I already mentioned, since that's exactly what it's there for.
These solutions aren't quite as clean as the arrow function, but they're nice to know about in case you need to support IE and don't want to use Babel.
The optional second argument not only works for the forEach()
methods (both Array
and NodeList
), but also the following array instance methods:
Array.prototype.every()
Array.prototype.filter()
Array.prototype.find()
Array.prototype.findIndex()
Array.prototype.flatMap()
Array.prototype.map()
Array.prototype.some()
If you find the this
keyword confusing, you're not alone. I recommend checking out this excellent and thorough video by Steve Griffith: