Reputation: 51
I'm a beginner development in TypeScript. I thought typescript could solve all my problems with this scope in JavaScript, but it doesn't seem so. See the example code below:
class Car{
private name : string;
private velocity: number;
constructor ( name:string){
this.name = name;
this.velocity = 0;
}
private speedUp (incrementer: number){
this.velocity += incrementer;
}
public pressAccelerator (power: number){
console.log(this); //here this is a Car object
setTimeout(
function(){
// here is a Timeout object - WTF!!!
// was't this typeScript?
// what's up whit my "this" object scope?
console.log(this);
this.speedUp(power*1.34); //TypeError: this.speedUp is not a function
},
1000
);
}
public getVelocity():number{
return this.velocity;
}
}
let myCar = new Car("Mercedes");
myCar.pressAccelerator(2);
console.log(myCar.getVelocity());
Why does this
in the this.speedUp
method, doesn't point to the car object?
Which is a practical way to solve?
Upvotes: 1
Views: 1175
Reputation: 22083
You suggest to get use to the arrow notation:
class Car {
private name : string;
private velocity: number;
constructor (name: string) {
this.name = name;
this.velocity = 0;
}
private speedUp = (incrementer: number): void => {
console.log(this);
this.velocity += incrementer;
}
public pressAccelerator = (power: number): void => {
console.log(this); //here this is a Car object
setTimeout(() => this.speedUp(power*1.34), 1000);
}
public getVelocity = (): number => {
return this.velocity;
}
}
let myCar = new Car("Mercedes");
myCar.pressAccelerator(2);
console.log(myCar.getVelocity());
Which will be compiled as:
var Car = /** @class */ (function () {
function Car(name) {
var _this = this;
this.speedUp = function (incrementer) {
console.log(_this);
_this.velocity += incrementer;
};
this.pressAccelerator = function (power) {
console.log(_this); //here this is a Car object
setTimeout(function () { return _this.speedUp(power * 1.34); }, 1000);
};
this.getVelocity = function () {
return _this.velocity;
};
this.name = name;
this.velocity = 0;
}
return Car;
}());
var myCar = new Car("Mercedes");
myCar.pressAccelerator(2);
console.log(myCar.getVelocity());
As you can see, the typescript will fix that closure. You can read more here
A problem it won't fix is if you define a function with a scope within the timer callback: (non arrow function)
setTimeout(
function(){
// here is a Timeout object - WTF!!!
// was't this typeScript?
// what's up whit my "this" object scope?
console.log(this);
this.speedUp(power*1.34); //TypeError: this.speedUp is not a function
},
1000
);
Upvotes: 1
Reputation: 12114
Use an arrow function, which retains the this
:
public pressAccelerator (power: number){
console.log(this); //here this is a Car object
setTimeout(
() => {
console.log(this);
this.speedUp(power*1.34);
},
1000
);
}
Upvotes: 2
Reputation: 4899
I don't know if it's elegant but this works:
public pressAccelerator (power: number){
console.log(this); //here this is a Car object
let self = this;
setTimeout(
function(){
console.log(self);
self.speedUp(power*1.34);
},
1000
);
}
Upvotes: 0