The Wayback Machine - https://web.archive.org/web/20210414081120/https://github.com/microsoft/TypeScript/issues/10285
Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scope of this is lost when passing a member function to setInterval #10285

Open
leewinder opened this issue Aug 11, 2016 · 8 comments
Open

Scope of this is lost when passing a member function to setInterval #10285

leewinder opened this issue Aug 11, 2016 · 8 comments

Comments

@leewinder
Copy link

@leewinder leewinder commented Aug 11, 2016

TypeScript Version: 1.8.10

When passing a member function to setInterval, the scope of 'this' is lost within the callback, though the structure of the code (given experience of any object orientated language) indicates it shouldn't be.

Example code

export class SetIntervalTest {
  private someNumber: number = 1;

  trigger() {
      setInterval(this.setIntervalCallback, 400);
  }

  private setIntervalCallback() {
      console.log(this.someNumber);
  }
}  

Expected behavior
When console.log(this.someNumber); is called, the scope of this is within the scope of the SetIntervalTest interval instance, printing '1'.

Actual behavior:
The scope of this is pulled from global scope, resulting in this.someNumber being 'undefined'. If that isn't possible, the compiler should indicate the expected behaviour is not what you're going to get.

To fix this i need to change 'setInterval(this.setIntervalCallback, 400);' to 'setInterval(() => this.setIntervalCallback(), 400);' so 'this' is correctly scoped in the callback.

@leewinder
Copy link
Author

@leewinder leewinder commented Aug 11, 2016

Thanks @RyanCavanaugh, still should be either caught at the compile stage (which is possible if it's expected behaviour) and flagged as a warning, or the generated JS structured should generate the obvious intent.

@RyanCavanaugh
Copy link
Member

@RyanCavanaugh RyanCavanaugh commented Aug 11, 2016

See "something about this" in https://github.com/Microsoft/TypeScript/wiki/FAQ#common-feature-requests

You can have the "correct" code generated by using an arrow function:

    private setIntervalCallback = () => {
      console.log(this.someNumber);
    };
@kitsonk
Copy link
Contributor

@kitsonk kitsonk commented Aug 11, 2016

Also, note that this behaviour is consistent with the ES6 runtime behaviour. Methods are not statically bound to the instance.

@mhegazy
Copy link
Contributor

@mhegazy mhegazy commented Sep 7, 2016

There are two parts to get this working correctelly:

  1. change the definition in lib.d.ts to include this: void:
declare function setInterval(handler: (this: void, ...args: any[]) => void, timeout: number): number;
  1. make methods have this type by default, this is tracked by #10288, to work around this the definition of the method can be private setIntervalCallback(this: this) { ... }. with both these changes in you would see the error as desired.
@mhegazy mhegazy added the Suggestion label Sep 7, 2016
@mhegazy
Copy link
Contributor

@mhegazy mhegazy commented Sep 7, 2016

I would say the change to the library should be done either ways.

@mhegazy mhegazy added this to the TypeScript 2.1 milestone Sep 7, 2016
@mhegazy mhegazy modified the milestones: TypeScript 2.1, Future Sep 29, 2016
@gdh1995
Copy link
Contributor

@gdh1995 gdh1995 commented Jan 26, 2017

I think here TypeScript should keep the same semantics just as ES6, but not force it bound by default.

@zijianhuang
Copy link

@zijianhuang zijianhuang commented Sep 9, 2019

@leewinder ,

setInterval(()=>this.setIntervalCallback(), 400);

should be just working fine so that the callback can see this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
7 participants