Home > Mobile >  Inconsistency of `this` when debugging a typescript program under VS code
Inconsistency of `this` when debugging a typescript program under VS code

Time:04-27

edit: I think I have seen this problem when using chrome to debug my full application. So, not sure if this is a typescript issue or a VScode issue.

I was about to submit when I thought I should try it using chrome as the debugger instead of VS code. Chrome works as expected, but VS code shows the problem illustrated below.

I distilled the following down from a larger program that was giving me some strange behavior when examining things in the debugger. The program appears to work correctly in terms of what it prints out, but if I run it in VS code or attach to a running process, when inspecting the value of this inside somePrivateArrowFunc, I see different results in the debugger than are printed out to the console:

class MyClass {
  someField: number = 123;

  private somePrivateArrowFunc = () => {
    console.log("somePrivateArrowFunc", this);
  };

  funcRefs = [this.somePrivateArrowFunc];

  funcRef = this.somePrivateArrowFunc;

  public somePublicRegularFunc() {
    console.log("somePublicRegularFunc", this); // debugger sees "this" as instance of MyClass
    for (let f of this.funcRefs) {
      f(); // debugger sees "this" as the global object inside somePrivateArrowFunc
    }
    this.funcRefs[0](); // debugger sees "this" as an array containing f inside somePrivateArrowFunc
    this.funcRef(); // debugger sees "this" as an instance of MyClass inside somePrivateArrowFunc
  }
}

var c:MyClass = new MyClass();

c.somePublicRegularFunc();

The output printed to the console indicates that the value of this is always an instance of MyClass, but a breakpoint on that same console.log line sees 3 different behaviors:

somePublicRegularFunc MyClass {
  someField: 123,
  somePrivateArrowFunc: [Function (anonymous)],
  funcRefs: [ [Function (anonymous)] ],
  funcRef: [Function (anonymous)]
}
somePrivateArrowFunc MyClass {
  someField: 123,
  somePrivateArrowFunc: [Function (anonymous)],
  funcRefs: [ [Function (anonymous)] ],
  funcRef: [Function (anonymous)]
}
somePrivateArrowFunc MyClass {
  someField: 123,
  somePrivateArrowFunc: [Function (anonymous)],
  funcRefs: [ [Function (anonymous)] ],
  funcRef: [Function (anonymous)]
}
somePrivateArrowFunc MyClass {
  someField: 123,
  somePrivateArrowFunc: [Function (anonymous)],
  funcRefs: [ [Function (anonymous)] ],
  funcRef: [Function (anonymous)]
}

I got these results using Version 4.6.3 of tsc and node v16.13.0 (I also saw the same with earlier versions of both).

CodePudding user response:

It seems to me that what you see as this with the debugger is simply and really NOT the this that is actually used by your somePrivateArrowFunc arrow function.

As expected by design, and as confirmed by your console output, this in the arrow function is easily predictable and always the same: it is the value where the arrow function is expressed. In your case, the arrow function is expressed during the instance initialization, hence it is your instance.

But the this that you inspect in your debugger is rather the context, i.e. what a normal function would get as this. Which, therefore, depends on how you called the function:

  • f(): no context, this is global
  • funcRefs[0](): context is funcRefs, i.e. the array
  • this.funcRef(): context is the same as the call c.somePublicRegularFunc(), hence is c, i.e. an instance

If you turn your arrow function into a normal function, then your console output will reflect the this that you get in the debugger.

CodePudding user response:

I found that using a newer target language version (es2022 instead of es5 or es6) fixed the problem. The debugger sees the correct value of this in all 3 scenarios.

  • Related