Anser for year 2024
A lot of information here is quite obsolete. This answer is focused on how to resolve in 2024+
- Use instances when calling function
- never take function "out of its instance". If you need to call that function later, just keep the whole instance, for example like this:
class A {
constructor(id) {
this.id = id;
}
someFunction(){
console.log(this);
}
}
const a1 = new A(5);
const a2 = new A(20);
const arr = [a1, a2];
// some business logic
arr.forEach(a => a.someFunction());
- Do not overuse
this
Do not use this
and classes if not necessary. When you require files like repositories, controllers, services, it by default creates singletons, which is something you want (its basically like @Autowired in Java, but native).
For example somethingService.js
can look similar to the code below:
const someDefaultValue = 10;
export function doSomething() {
console.log(someDefaultValue);
}
Then you dont have to think about using doSomething()
as somethingService.doSomething()
or doSomething()
directly. (it will work the same)
- Use apply/call/bind
I am personally not fan of using apply
(or call
or bind
which is basically the same, just called a bit differently) extensively, from my experience it can bring even more chaos into code. But there can be situations where you might need it, so I will list it here. You can basically "inject" this
with whatever object you like inside function.
class Simple {
constructor(id) {
this.id = id;
self = this;
}
showThis(text) {
console.log(this, ` ** ${text} **`)
}
}
const simple = new Simple(25);
const showThisFn = simple.showThis;
showThisFn("using it without apply");
showThisFn.apply(simple, ["using it with apply"])
showThisFn.call(simple, "using it with call - basically same as apply, only syntactic sugar difference today")
boundShowThisFn = showThisFn.bind(simple);
boundShowThisFn("now it is bind with the instance, so you dont have to specify it when calling it");
- Use Arrow Function => correctly
If you have function inside function and you use this
, the arrow function will pass the this
context in the way you would expect. Using function
keyword will change the context of this
.
(basically use arrow functions whenever it is possible and you are safe)
class A {
constructor(baseValue) {
this.baseValue = baseValue;
}
doMathArrowFunction(arr){
arr.forEach(item => {
console.log(`Arrow function: item is ${item} and this?.baseValue is ${this?.baseValue}`);
console.log(item + this?.baseValue);
});
}
doMathOldWay(arr) {
arr.forEach(function(item) {
console.log(`Old fashion function: item is ${item} and this?.baseValue is ${this?.baseValue}`);
console.log(item + this?.baseValue);
});
}
}
const x = [1,2];
const a = new A(10);
a.doMathArrowFunction(x);
a.doMathOldWay(x);
In past (before Arrow function existed) it was often resolved with self/that
keywords. If you encounter it and want to know more - check accepted answer in this thread.