If in JavaScript you've ever wondered when to use arrow functions and when to use traditional functions, or simply what the difference is between the two options, you've come to the right place!
Notes:
when I refer to a traditional function, I'll be talking about a function declared with the keyword 'function'
an arrow function (or arrow function in English) is a function declared with the compact syntax () => {}
Part 1: This
The first difference between the two options is the handling of "this"; indeed, arrow functions retain the "this" of the context in which the function was called, which is not necessarily the case with a traditional function. Here is an example to illustrate: language=js class MyClass { prop = "hehe"; testArrow() { const f = () => { console.log(this.prop); }; f(); } testFunction() { function f() { console.log(this.prop); } f(); } } const instance = new MyClass();
When we make the call to: instance.testArrow() there will be no error because the 'this' of the class instance is retained, however if we try: instance.testFunction() There will be a lovely JavaScript error "Cannot read properties of undefined" ...
To understand this error, you need to know a bit more about the 'this' keyword and JavaScript in general:
in a traditional function, "this" corresponds to the global object
in a traditional function AND in strict mode ("use strict";) "this" will be undefined
the body of a class is always executed in strict mode
However, in our case, the function is declared within a class, so in strict mode, thus "this" will be undefined, hence our JavaScript error "Cannot read properties of undefined".
Bonus:
If we replace our "testFunction" method in the "MyClass" class with the following code:
testFunctionBinded() {
function f() {
console.log(this.prop);
}
f.bind(this)();
}
This method is identical except for the call to f().
Indeed, by calling f and manually binding it to the correct "this" with the following syntax: f.bind(this)(); There will be no error when calling instance.testFunctionBinded()
Part 2: JavaScript Hoisting
In JavaScript, when using the keyword "function", you can use this function before its declaration (as long as you stay within the same block); this is called hoisting.
In some cases, it's quite pleasant, but very often, it leads to errors that are difficult to debug, for example:
if (true) {
function a() {
console.log("1");
}
if (true) {
a();
function a() {
console.log("2");
}
}
}
Here, we declare a first function "a", then in the following block, at the beginning of the block we call a() and at the end of the block we declare another function "a". When a() is called, it's not the function we expected that's called, since the second function "a" is "hoisted"...
Often, arrow functions are kept in a "const" or a "let", which makes the code much easier to read because it's readable from top to bottom, thereby eliminating the bug mentioned above.
There you have it! Personally, I prefer to use arrow functions, because the behaviour is much easier to predict and the code is easier to read!