JavaScript is a very popular and widely used programming language. Initially it was developed only as a scripting language, but now it is doing way more than that. It's community is growing so is the Javascript.
As the new features is being added frequenty, it is hard to write optimized and clean code, mostly happens when you are a beginner.
Today I'm going to show you some of the best practice that you can follow to write optimized and clean code.
So with out any further due, let's get started
-
Chain array methods
Yes, you read it correct, the thing that we use more often is Array Prototype methods like,
map
,filter
,find
,reduce
basic scenario will be mapping through the filtered list, instead of storing the filter result in a varibale and then mapping on, we can directly chain the methods.
const userList = [
{
name: 'Jhon Doe',
age: 26,
occupation: 'Software Engineer',
},
{
name: 'Kapil',
age: 19,
occupation: 'Student',
},
{
name: 'Matt',
age: 32,
occupation: 'Software Architect',
},
];
const mappedUsers = userList.filter(user => user.age > 26)
.map(user => ({ isVerified: true, ...user}))
.reduce(...)
2.
Logical assignment
There might be hte scenario where we need to assign something when any given variable is null or undefined, normal way using if
would be like this:
let userProfile;
let value = {
name: 'someValue',
};
if(userProfile === null || userProfile === undefined) {
userProfile = value
}
// OR
if(!userProfile) {
userProfile = value
}
we can simply do assign using logical or nullish collision operator, like this:
userProfile ??= value;
// OR
userProfile &&= value
3.
Parallel API calls
While building any Application, mostly in frontend, sometimes we might need to call several API simultaneously, if the APIs are not dependent on each other, we can send a paraller request using Promise
in Javascript
const getData = async () => {
try {
const first = await fetch();
const second = await fetch();
const third = await fetch();
const fourth = await fetch();
} catch (err) {
// ...
}
}
Instead of this we can send the parllel call,
const getData = async () => {
try {
const [ first, second, thrird, fourth] = await Promise.all([
fetch(),
fetch(),
fetch(),
fetch(),
])
} catch (err) {
// ...
}
}
we can also use
Promise.allSettled()
instead ofPromise.all()
based
4.
Using Objects instead of Switch for event binding
In most of the applications that we develop, there are some scenario where we need to handle events, and mostly we do that using switch statement or if...else,
const handleEvent = (event) => {
switch(event) {
case 'success': {
// handleSuccess
}
case 'error': {
// handle error
}
case 'pending': {
// handle pending
}
default: {
// handle default
}
}
}
instead of doing this, we can simply create the object with event as key
and function as its value
something like this:
const eventHandler = {
success: handleSuccess,
error: handleError,
pending: handlePending
}
const handleEvent = (event) => {
const handler = eventHandler[event] ?? handleDefault;
handler();
}
here we need to use bracket notation to call the appropriate functions out of object.
5.
Doing one thing in a function
So, the basic behaviour of a function is to perform a particular task, and whatever we write in it, will be executed.
making a single function perform every thing will make the code hard to read, lenghty, and hard to debug.
Dividing the single functionality inside a function and calling the rest one after or inside the other fucntion, will help for better understanding of code and make our code easy to debug
the best scenario for this will be user registeration
const signupUser = () => {
// checking for existing user
// password encryption
// creting new user
}
so doing all of this stuff in one function make it more clumsy, what we can do instead is
const signupUser = () => {
const isUserAlreayExist = checkExistingUser(/* username */);
// handle if user already Exist
const hashedPAssword = encryptPAssword(salt, password);
createUserAndReturn(/* user data */)
}
6.
Using console.trace()
To check some result and or sometime to debug small things, we use console.log()
right?
which just give us the message that we wrote.
but some times in bigger applications, we can have log statements, and keeping track of the log statement, which log represents which part might get a little hard, so to prevent that we can use console.trace()
The trace() method displays a trace that show how the code ended up at a certain point.
It returns some additional information, apart from the message that we wrote, the information includes from where this statement has been logged, from which function and line number.
7.
Using Logpoint in vscode
While debugging the application we add breakpoints to stop the execution of the program at a certain point, but sometime we just wnat to see if the particular code got executed or not, for for that we can add Logpoint
the result will show the output in the console as it has been logged while going through that point, in this way we don't event have to worry about the console statements in production.
We can add the logpoint by right clicking
the line number in the vscode
Some honourable mentions
- Use
async / await
instead of promise callback chain - Use Typescript for larger applications.
- Use comments in the code where ever necessary.
- Use
destructing
instead of chainingobject
or usingindexe
in array - Use less third part library (only use when necessary).
- Read...
Conclusion
These are some of the best practices that I follow to make my code clean, neat, readable and easy to debug. The key for clean code is an ongoing journey as the Javascript is contionusly evolving language.
I hope this might help you in your coding journey.
Happy coding!
Top comments (9)
The last point is heavily disputed and there are a lot of opinionated people on either side.
My position is: use what fits your case best. You can also mix
await promise emitter().catch(...)
for extra conciseness.Might want to check number 4. The sample code is not correct.
Also, you might want to consider switching on syntax highlighting in the code samples. You can do this by adding
js
immediately after the opening backticks of the code blockThanks @jonrandy
Logical assignment
There might be hte scenario where we need to assign something when any given variable is null or undefined, normal way using if would be like this:
It's much easier to write, but the readability is so bad.
Some of these can be dangerous practices.
Chaining too much array methods, for instance, will make it significantly harder to debug if any problem appears, not to mention all the extra allocations.
You shouldn't have to fetch several requests at the same time, it slows them down and creates extra load on the server. Promise.all and similar are a workaround for the cases when you don't have any control over the server but still need to make sure that all data is delivered.
There's nothing wrong with using switch or chaining promises, or using a for loop instead of a functional style and mutating the array directly when that makes sense.
JavaScript is one of the most versatile languages and the only best practice is has is:
Nice Post! One thing I would like to point out, Parallel API calls can be detrimental sometimes if you go overboard with them. Say my function did 5 API calls simultaneously, and this function was called at a high rate in my code you can actually end up causing a lot of load on the target server. Moreover, most APIs also have rate limiting setup and successive requests might be blocked.
A way to circumvent this is to use a Queue of promises and process promises from the queue at a fixed concurrency level (say 2 at a atime, or 3 at a time). P-queue is a great library to achieve this.
Dear Vinay, FYI we've added your blog post on a GitHub project gathering content about best coding practices :)
github.com/promyze/best-coding-pra...
nullish collision
butnullish coalescing
assignment. And thisuserProfile &&= value
does exact opposite than you described. IfuserProfile
has falsy value, then it keeps it, if not, then the value is overwritten byvalue
.It's not destructing but destructuring...