arrow vs regular function
Differences
Inside a regular function, the
this
value is dynamic. It depends on how the function is invoked.const person = {
firstName: '',
lastName: '',
getFullName: function () {
return `${this.firstName} ${this.lastName}`;
},
};
person.firstName = 'Foo';
person.lastName = 'Bar';
person.getFullName(); // 'Foo Bar'Arrow function does not have
this
. Accessingthis
inside an arrow function will refer to thethis
of its closest non-arrow parent function.const person = {
yearOfBirth: new Date().getFullYear(),
getAge: () => {
return new Date().getFullYear() - this.yearOfBirth;
},
};
person.yearOfBirth = 2000;
person.getAge(); // NaNIt is worth noting that calling
arrowFunction.call(thisValue)
orarrowFunction.apply(thisValue)
do not change thethis
value.We can use the
new
keyword with a regular function to create new object.function Person(name, age) {
this.name = name;
this.age = age;
}
const foo = new Person('Foo', 42);On the other side, arrow functions do not own
this
value, hence they cannot be invoked with thenew
keyword.const person = (name, age) => {...}
// ERROR: person is not a constructor
const foo = new person('Foo', 42);Inside a regular function, we can use
arguments
which represents an array-like object of passed arguments. It is very useful if we want to access the parameters of a function whose number of parameters are dynamic.For example, the function below calculate the average of parameters:
function average() {
const args = [...arguments];
return args.reduce((a, b) => a + b) / args.length;
}
average(1, 2); // 1.5
average(1, 2, 3); // 2Arrow functions do not have
arguments
. Callingarguments
inside an arrow function will return the arguments of closest non-arrow parent function.But it is still possible to get the list of dynamic passed parameters by using the rest parameters
const average = (...args) => args.reduce((a, b) => a + b) / args.length;
average(1, 2, 3, 4); // 2.5
average(1, 2, 3, 4, 5); // 3We have to use the return statement in a regular function to return a result.
function sum(a, b) {
return a + b;
}However, in an inline arrow function that contains only one expression, we can implicitly return the value by omitting the curly brackets. The
sum
function above can be rewritten as follow:const sum = (a, b) => a + b;
Plus, arrow function also does not require parentheses if it has only one parameter:
const sumOfArray = (arr) => arr.reduce((a, b) => a + b, 0);
In non-restrict mode, regular functions allow us to use duplicate named parameters.
The following declaration is accepted:
function double(x, x) {
return x + x;
}
double(3, 2); // 4
double(3, 5); // 10This usage is not allowed in strict mode:
'use strict';
function double(x, x) { ... }
// ERROR: Duplicate parameter name not allowedIt is not possible to use the same name for different parameters in arrow functions, no matter the strict or non-strict mode is enabled.
Good practice
If the inline arrow function consists of the <
, <=
, >
or >=
operator, it is advised to wrap the function body in parentheses.
Looking at the two versions below, it is easy for the first variant to cause a misleading.
// Bad
const compareToZero = (a) => a <= 0 ? 0 : a;
// Good
const compareToZero = (a) => (a <= 0 ? 0 : a);
Tip
You can use an underscore to name the argument which is not used in an arrow function. It makes the code more readable.
// No arguments
const noop = (_) => {};
const range = (min, max) =>
Array(max - min + 1)
.fill(0)
.map((_, i) => min + i);
Resource
You can find many useful arrow functions that have only single line of code at 1 LOC website.