I have a simple JSFiddle here demonstrating my issue.
I have this JavaScript code:
var b = document.getElementById("b");
function A() {
this.f = "1";
}
A.prototype.t = function() {
b.innerHTML = this.f;
};
var a = new A();
var l = a.t;
l();
Why is this
undefined when I try to call a.t? How do I recover that context without being overly verbose or storing too much?
In JavaScript, the this keyword refers to an object. Which object depends on how this is being invoked (used or called). The this keyword refers to different objects depending on how it is used: In an object method, this refers to the object. Alone, this refers to the global object.
A variable that has not been assigned a value is of type undefined . A method or statement also returns undefined if the variable that is being evaluated does not have an assigned value. A function returns undefined if a value was not returned .
What is context? Context is always the value of the this keyword which is a reference to the object that “owns” the currently executing code or the function where it's looked at. We know that window is a global object in the browser so if we type this in the console and it should return window object, which it does.
functions are data in memory stack, so when you define another function with the same name, it overrides the previous one. Show activity on this post. Well obviously you're not meant to define the same function twice. However, when you do, the latter definition is the only 1 that applies.
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):
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With