You need to use bind
(or a similar approach) when:
- The function is a traditional (
function
keyword) function or method (in a class
or object literal), and
- That function will be called either in a way that doesn't set
this
explicitly or that sets it to an incorrect value
The reason is that with a traditional function or method, the value of this
is set by the caller, not a part of the function itself. (Details here and here.)
For example, consider:
const obj = {
method() {
console.log(this === obj);
}
};
Now, when we do obj.method()
, we're using syntax (calling the result of a property accessor operation) to specify what this
will be, so:
obj.method();
// => true
But suppose we do this:
const m = obj.method;
Now, just calling m()
will set this
to the default this
(undefined
in strict mode, the global object in loose mode):
m();
// => false
Another way we can explicitly set this
for the call is via call
(and its cousin apply
):
m.call(obj);
// => true
Some functions that call callbacks let you specify what this
to use. forEach
does, as an argument just after the callback:
[1].forEach(m, obj);
// ^ ^^^---- the value to use as `this` in callback
// \-------- the callback to call
// => true
Here's a live example of those:
const obj = {
method() {
console.log(this === obj);
}
};
obj.method();
// => true, `this` was set to `obj` because you did the call on the
// result of a property accessor
const m = obj.method;
m();
// => false, `this` was the default `this` used when `this` isn't
// specified explicitly via syntax or `call`
m.call(obj);
// => true, `this` was explicitly set via `call`
[1].forEach(m, obj);
// => true, `this` was explicitly set via `forEach`'s `thisArg` argument
So any time you have a function (such as the callback of a forEach
, or an event handler), you need bind
or a similar mechanism to ensure that the correct this
is used.
This isn't true for some other kinds of functions, just traditional (function
keyword) functions and methods (such as obj.method
above). An arrow function closes over this
instead of using the one supplied by the caller, and a bound function (result of using bind
) has this
bound to it and so ignores any this
supplied by the caller.