2

I have a class, which has a method that uses this. I 'newed up' an instance of this object and passed on its method to a variable in the global context. If I then call my global function this is undefined.

class Tests {
  logThis() {
     console.log(this);
  }
}

const globalFunc = new Test().logThis;

globalFunc(); // undefined

Now, if I had just used an object literal then this is is global.

const someObject= {
    logThis2: function() {console.log(this)}
}

const globalFunc2 = someObject.logThis2;

globalFunc2(); // global object

In both cases the global object owns the code and should be supplying this in the globalFunc execution context. So why the difference in this for a class generated method?

cham
  • 4,095
  • 4
  • 32
  • 48
  • JavaScript classes are always in strict mode. Other functions / contexts are not in strict mode unless there is a `"use strict";` statement. In strict mode `this` is `undefined` instead of the global object when it has not been specified. – Paul Jul 06 '19 at 22:43
  • Thanks @Paulpro . So what about when the method is assigned. Is the original `this` also bound to the method. – cham Jul 06 '19 at 22:56
  • 1
    No, see this question for information about `this` in general: https://stackoverflow.com/questions/3127429/how-does-the-this-keyword-work . functions don't get a `this` bound to them. `this` is determined at the time the function is called, not when the function is defined. `x.foo()` calls the function `x.foo` with `this === x`. `var y = { bar: x.foo }; y.bar( );` calls `x.foo` with `this === y`. Whereas `var z = x.foo; z( );` calls `x.foo`, with no `this`, which will cause it to be `undefined` in strict mode but for legacy/bc reasons it will be the global object in non-strict mode. – Paul Jul 06 '19 at 22:59
  • You are storing a reference to the prototype , not to a direct property of the instance object. Would have to make `logThis` a direct property in the class constructor to do what you want. `constructor(){ this.logThis = this.logThis.bind(this) }` – charlietfl Jul 06 '19 at 23:00
  • 1
    Sorry @Paulpro I still don't get it cause in your example z is not in a class (ie not in strict mode) and is in the global context. That is the state of things at the time of the call??? – cham Jul 06 '19 at 23:12

1 Answers1

2

All classes, including their methods are evaluated in strict mode¹. Whenever a function gets created, and "its body is in strict mode"², then the function's internal [[mode]] property gets set to "strict". That will then let this evaluate to undefined when the function gets called without a context.


Relevant quotes from the spec:

1:

All parts of a ClassDeclaration or a ClassExpression are strict mode code

~ ES 262, 10.2.1 Strict Mode Code


2:

  1. If the function code for this MethodDefinition is strict mode code, let strict be true. Otherwise let strict be false.

[...]

  1. Let closure be FunctionCreate(kind, UniqueFormalParameters, FunctionBody, scope, strict, prototype).

  2. Perform MakeMethod(closure, object).

~ ES 262, 14.3.7 Runtime Semantics: DefineMethod

Community
  • 1
  • 1
Jonas Wilms
  • 106,571
  • 13
  • 98
  • 120