Mimic Bound Method in JavaScript
Because this keyword is weird and JavaScript doesn’t have bound method, we often need to bind methods to instances manually. Without it, the following code can fail:
const ron = new Person("Ron");
// Oops: `this` got rebound to undefined when calling `greet`
setTimeout(ron.greet, 1000);
Here are three ways to fix the problem.
Manually Bind Pattern
One way to work around this problem is to use the following pattern:
class Person {
constructor(name) {
this.name = name;
// manually bind greet with a fixed this
this.greet = this.greet.bind(this);
}
greet() {
console.log(`Hello, my name is ${this.name}.`);
}
}
Arrow Function as Method
Alternatively, we can make greet
a property with arrow function to ensure this
isn’t rebound when greet
is used
class Person {
name;
constructor(name) {
this.name = name;
}
greet = () => {
console.log(`Hello, my name is ${this.name}.`);
};
}
Decorator
We can also make a bound
decorator to solve this issue:
function bound(value, {kind, name, addInitializer}) {
if (kind === 'method') {
addInitializer(function () { // (B)
this[name] = value.bind(this); // (C)
});
}
}
In here, bound
isn’t return anything, so when decorating it will leave the original method along. Instead, it uses addInitializer
to replace the method in the class with a function bound by a fixed this
.
And here it is in action:
class Person {
name;
constructor(name) {
this.name = name;
}
@bound
greet() {
console.log(`Hello, my name is ${this.name}.`);
}
}
parent: bind tags:javascript