Keep Babel Class As `this` When Using A Member Function In `settimeout`
Solution 1:
My question is, am I doing something wrong with ES2015 or babel here?
Actually, it's a expected JavaScript behavior and is related to how this is assigned in the language.
Consider the code below (no ES6, no babel...):
var obj = {
key1: 'value1',
key2: function() {
console.log(this);
}
}
obj.key2(); //will print objvar callback = obj.key2; //assigned the function reference to some random variablecallback(); //will print Window/global objectAs you can see, this is defined when the function is invoked, not when it's declared, and depends how it's being called.
That's exactly what's happening inside setTimeout, or in any function that receives a function as a parameter:
/* fake */
function setTimeout(fnCallback, time) {
/* wait and when the time comes, call your callback like this: */fnCallback(); //'this' will be Window/global
}
"Workarounds":
In order to pass the desired context (in the example above), we can force the context:
using
.bind:var callback = obj.key2.bind(obj); callback(); //will print objor using
.call:var callback = obj.key2; callback.call(obj); //will print obj
Or we can pass an anymous function an call our object from inside:
setTimeout(function() {
//here, 'this' is Window/global, because the anonymous function is being called from a callback assignment
obj.key2(); //will print obj
}, 3000);
In your example
So, in your example, in order to properly set the setTimeout callback and ensure that baz() will receive the class context, you can:
bind the function when setting it as a callback:
setTimeout(this.baz.bind(this), 1000);in your class constructor,
bindthebazmethod once; so, everytime it's called, will be assigned the class context. Like this:classFoo{ constructor() { this.baz = this.baz.bind(this) } bar(){ setTimeout(this.baz, 1000); } baz(){ console.log("this message should repeat roughly once per second"); this.bar(); } }Use
arrow functions. Another way of specifying thethiscontext is usingarrow functions, that, actually, ensure thethisassignment is done through lexical scope (not anymore in the function invocation, but in the function declaration).setTimeout(() =>this.baz(), 1000); // ^^^^// 'this' here is your class, will pass your class as 'this'// to the baz() method, due to the dot beforeDifferent from:
setTimeout(function() { this.baz(); }, 1000); // ^^^^// 'this' here is Window/global, will thrown undefined method
Post a Comment for "Keep Babel Class As `this` When Using A Member Function In `settimeout`"