0

Why does the this in the prototype refer to the global context while the this in the declaration refers to the function? Even when trying to explicitly set the context of this it still refers to the global context.

var Foo = function (a) {
  console.log(this); // this will refer to global context
  this.bar = () => {
    // this refers to function context
    return a;
  };
};


Foo.prototype = {
  biz: () => {
    return this.bar(); // this this will refer to global context
  },
};

var f = new Foo(7);
f.biz(); // this.bar is not a function
f.biz.call(f); // this.bar is not a function
Matthew Moran
  • 1,457
  • 12
  • 22

1 Answers1

1

Because you declared the biz method as an arrow function. You should generally not do that because an arrow function retains this when it is declared (not when it executes).

Replace biz with a regular function like this:

var Foo = function (a) {
  console.log(this); // this will refer to global context
  this.bar = () => {
    // this refers to function context
    return a;
  };
};


Foo.prototype = {
  biz() {
    return this.bar();
  },
};

var f = new Foo(7);
f.biz(); // Works
f.biz.call(f); // Works even if not needed
Guerric P
  • 30,447
  • 6
  • 48
  • 86
  • If it retains `this` when it's declared, why doesn't the `this` in `this.bar` continue to refer to the global context? Is it not getting it's context from `f` when it's called with `f.bar()`? – Matthew Moran Aug 01 '21 at 18:12
  • @MatthewMoran because when it's declared, `this` wasn't `window`. – VLAZ Aug 01 '21 at 18:14
  • How is it not the window? The console log above it refers to the global context. – Matthew Moran Aug 01 '21 at 18:15
  • @MatthewMoran `this.bar` is being declared in the context of the constructor, where `this` is what you expect (the current instance) – Guerric P Aug 01 '21 at 18:15
  • Why is there a different between the `this` in the log above `this.bar` and `this.bar`? – Matthew Moran Aug 01 '21 at 18:16
  • @MatthewMoran "*The console log above it refers to the global context*" only if you call `Foo` without `new`. You don't do that, so `this` is an instance of `Foo`. https://jsbin.com/zazasus/edit?js,console – VLAZ Aug 01 '21 at 18:17
  • @VLAZ, the log prints out `this` as the global context when using new as well. It prints out when the instance is created. – Matthew Moran Aug 01 '21 at 18:19
  • @MatthewMoran see the example I posted. It doesn't. – VLAZ Aug 01 '21 at 18:20
  • Ah I see my confusion. Running in Node (not strict mode) it shows `this` in the log to be `{}` which is the same as the global context in node not in strict mode so I assumed it was referring to the global context. Running it in the browser, I see it refers to the instance of Foo. – Matthew Moran Aug 01 '21 at 18:25
  • 2
    @MatthewMoran When you call a function with `new` the value of `this` will *always* be an instance of the function. That's how the `new` operator works - it creates an instance then calls the function with `this` set to it. If you *don't* use `new`, then `this` will be undefined. Or the global object in sloppy mode. Unless you override it with `.call`, for example. Arrow functions are not constructable, they cannot be called with `new`. – VLAZ Aug 01 '21 at 18:28