Like any kind of apps, JavaScript apps also have to be written well.
Otherwise, we run into all kinds of issues later on.
In this article, we’ll look at some best practices for working with arrow functions.
Placement of Arrow Functions
The placement of arrow functions is all about preferences.
We can put them at the top level.
Also, we can place them inside objects or functions.
This is all up to us.
So we can write:
const person = {
getData: (id) => ajax(URL,{ id })
};
or:
export default id => person.getData(id)
or:
export const getPerson = id => person.getData(id)
or:
const getPerson = id => People.getData(id,onData)
We can place them at the top level, as exports or inside objects.
Returning Data
We should make sure that we write our return syntax properly.,
For instance, we can write:
const fn = prop => ( val => { return { [prop]: val }; } );
or:
const fn = (x, y) => {
return (
x > 3 ? x : y
);
};
If we have an expression, we should put them in parentheses.
Also, we should add the return
keyword unless our function only has one statement and only returns a short expression.
For instance, we can also write:
const cube = x => x ** 3;
This is also readable.
If we have arrow functions longer than that, then we should add parentheses, curly braces, and the return
keyword.
The Use of this
We shouldn’t use this
in callbacks that don’t need them.
For instance, if we have:
const squared = arr.map(a => a ** 2, this);
then we don’t need the this
since it does nothing.
Arrow functions don’t have their own this
, so this
references whatever value of this
is outside the function.
Therefore, this
shouldn’t be at the top level since it’s going to be undefined
under strict mode.
So having something like:
a => this.bar(a);
at the top level wouldn’t work.
Don’t Use the arguments Keyword
We should never use the arguments
keyword.
It’s used to get all the arguments passed into a traditional function.
It doesn’t with arrow functions.
Also, it’s an array-like iterable object so it doesn’t have any array methods.
Therefore, instead of using:
function sum() {
const numbers = [...arguments];
return numbers.reduce((a, b) => a + b);
}
We can use the rest operator instead by writing:
const sum = (...numbers) => {
return numbers.reduce((a, b) => a + b);
}
numbers
would be an array, so we can call reduce
on it.
The rest operator saves us typing and headaches.
Use of class
We can use class
for constructors.
Ideally, we minimize the use of them since they hold internal state and have methods that commit side effects.
Therefore, whenever we can, we use pure functions.
So we can write:
const rectangle = (height, width) => {
return {
height: height,
width: width
};
}
Instead of:
class Rectangle{
constructor(height, width) {
this.height = height;
this.width = width;
}
}
Don’t Use the delete Keyword
The delete
keyword removes a property from an object.
This means the object is mutated.
Therefore, it’s better to make a copy of an object without a property that we want.
Instead of writing:
delete foo.bar;
We can use something like Lodash to make a new object without a property:
const _ = require('lodash/fp');
const fooWithoutBar = _.omit('bar', foo);
Don’t Use the events Module
If we want to stick with functional programming, then we shouldn’t use the Node’s events
module.
It lets us make side effects by emitting and listening to events.
Instead, we can create pure functions to pass around data.
Conclusion
Writing pure functions makes our lives easier since they don’t commit side effects.
Also, we should be careful about how we return data in arrow functions.