Reputation: 672
I'm using classes in JS and providing a method from a class as a callback to some other function. The other function appears to call .bind()
on the method so when it runs this
no longer refers to an instance of the class.
Here's an example:
class Foo {
constructor () {
this.val = 10
}
bar() {
console.log(this.val)
}
}
function doSomething(callback) {
callback.bind(this)()
}
const a = new Foo()
doSomething(a.bar) // prints undefined
Is it possible to prevent the function from being rebound, and if not, is there any way to still access the instance the method was previously bound to?
Update: In my particular case, the function which re-binds the callback is a method of an object. As a workaround it's possible to store the class instance as a property of the other object and retrieve it that way.
Upvotes: 0
Views: 175
Reputation: 8010
Normal way to handle this is to bind all instance methods in the contructor, like this:
class A {
constructor() {
this.methodA=this.methodA.bind(this);
this.methodB=this.methodB.bind(this);
}
methodA() {
// do something with `this`
}
methodB() {
// do something with `this`
}
}
The advantage of binding it once in the contructor is that methods retain equality. If you use the method proposed by @Salketer, a.methodA.bind(a)!=a.methodA.bind(a)
since every bind creates a new instance. This makes it impossible to, for example, remove event handlers. If you bind them once at the beginning they retain equality.
Note also that binding the methods again won't change the value of this
again. So it's safe to pass these methods to functions that themselves call bind
.
Upvotes: 1
Reputation: 15711
It is unusual to pass instance methods like you are doing. You are getting undefined because they .bind(this)
but if they did not, you would get an error: Cannot read properties of undefined (reading 'val')
since this would be undefined.
Usually, a passed callback is either an anonymous function or a bound class method. I've added both as example in your code for you to see. The big benefit of using an anonymous function is that you would have access to the whole "calling" scope instead of just the object.
class Foo {
constructor() {
this.val = 10
}
bar() {
console.log(this.val)
}
}
function doSomething(callback) {
callback.bind(this)()
}
const a = new Foo()
doSomething(a.bar.bind(a))
doSomething(() => {
a.bar()
})
Upvotes: 1