Losing "this" context in JavaScript when passing around members [duplicate]
Why is this undefined when I try to call a.t?
Because in JavaScript, this
is set primarily by how the function is called, not where it's defined. a.t()
sets this
to a
within the call, but l()
sets this
either to undefined
(in strict mode) or the global object (in loose mode).
More (on my blog):
- Mythical methods
- You must remember
this
The only exceptions are "bound" functions (as with Function#bind
) or ES6's "arrow" functions (which get their this
from the context in which they're defined).
How do I recover that context without being overly verbose or storing too much?
Function#bind
is usually a good answer:
var l = a.t.bind(a);
l();
It returns a new function that, when called, calls the original with this
set to the first argument you gave bind
. (You can also bind other arguments.) It's an ES5 function, but if you need to support really old browsers, you can easily polyfill it.
If you just need to call l
with a specific this
value, and not always have it use that value, as Robert Rossmann points out you can use Function#call
or Function#apply
:
l.call(this, 'a', 'b', 'c'); // Calls `l` with `this` set to `a` and args 'a', 'b', and 'c'
l.apply(this, ['a', 'b', 'c']); // Calls `l` with `this` set to `a` and args 'a', 'b', and 'c' -- note they're specified in an array
JavaScript is functionally scoped,
To execute a function with the right value for this, you will need to bind it to the right object. For example,
var l= a.t.bind(a);
Because the context changes when you assign the function to a new variable. You could always just do a.t();
.