I get tired of writing code like this:
class Something {
constructor() {
this.method = this.method.bind(this);
this.anotherOne = this.anotherOne.bind(this);
// ...
}
}
It's time consuming and it's easy to forget to bind a method. I aware of the class fields proposal, but it's still Stage 3 and seems to come with some issues.
My current solution (based on this answer) looks like this:
class Something {
constructor() {
// Get all defined class methods
const methods = Object.getOwnPropertyNames(Object.getPrototypeOf(this));
// Bind all methods
methods
.filter(method => (method !== 'constructor'))
.forEach((method) => { this[method] = this[method].bind(this); });
}
}
This seems to work, but I'm wondering if there is a better way, or if this method has issues that I'm not aware of.
The problem I have run into is that if I don't bind my class functions in the constructor, I have to remember to call them "properly" later. For example:
const classInstance = new Something();
// This fails for a non-obvious reason
someAction()
.then(classInstance.method);
// This works of course but looks like we created a useless function if you don't know better
someAction()
.then(result => classInstance.method(result));
[React Component Class] Methods follow the same semantics as regular ES6 classes, meaning that they don't automatically bind this to the instance.
The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.
Binding this allows it to access the state and setstate inside the class. To avoid the need for binding we have something introduced in ES6 as arrow functions. Using the arrow function to call this. setState will lead to avoid the use of bind.
bind is a method on the prototype of all functions in JavaScript. It allows you to create a new function from an existing function, change the new function's this context, and provide any arguments you want the new function to be called with.
It seems a bit late to answer this question but there is no accepted answer so I will try my best for people come here after me.
this
for all methods, you can use "arrow" function:class Something {
constructor() {
// Don't need to bind `this`
}
doSomething = () => {
console.log(this); // `this` will be pointed to the instance
}
}
const s = new Something();
s.doSomething(); // => `this` is pointed to `s`
Note: just make sure the classes extending this class Something
will not use doSomething
method in its constructor
(eg: super.doSomething()
), otherwise you will get an error.
this
using .call()
or .apply()
, the value of this
depends on the way that method is calledFor example:
class Something {
constructor() {
// didn't bind `this` here
}
doSomething() {
console.log(this);
}
}
const s = new Something();
const funcA = s.doSomething;
const object = {
funcB: s.doSomething,
};
// these ways of calling `.doSomething()` result in different values of `this`:
funcA(); // => `this` is pointed to the global variable (`window` in browser environment)
window.funcA(); // => same as `funcA()`
s.doSomething(); // => `this` is pointed to `s`
object.funcB(); // =? `this` is pointed to `object`
Beside that, the implementation of .then()
method would be similar like this:
class Promise {
// ...
then(callback) {
// code...
callback(); // notice how the `callback` is called - not as a method of an object
// code...
}
}
With your code example, the way you pass the callback into .then()
method will affect the value of this
inside the callback:
const classInstance = new Something();
// `this` inside `classInstance.method` is pointed to `this` inside the
// `.then` method, not the `classInstance`, as `classInstance.method()`
// will be called as `callback()`
someAction()
.then(classInstance.method);
// `this` inside `classInstance.method` is pointed to `classInstance`,
// as the way the anonymous "arrow" function is called does not affect the way
// `classInstance.method` is called, so `this`'s value is controlled by the way
// you call it inside the callback (anonymous "arrow" function) of `.then()`
// method.
someAction()
.then(result => classInstance.method(result));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With