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 object
As 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 obj
or 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,
bind
thebaz
method 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 thethis
context is usingarrow functions
, that, actually, ensure thethis
assignment 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 before
Different 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`"