Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Losing "this" context in JavaScript when passing around members [duplicate]

Tags:

javascript

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?

like image 989
eatonphil Avatar asked May 27 '15 15:05

eatonphil


People also ask

What is the this keyword in JavaScript?

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.

Why this keyword is undefined in JavaScript?

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 in JavaScript?

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.

Can you define a function twice in JavaScript?

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.


1 Answers

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
like image 57
T.J. Crowder Avatar answered Oct 02 '22 15:10

T.J. Crowder