Better ways to write code in Javascript
Javascript is one of the top programming languages that’s been used for web application development. Nowadays the usage of Javascript is very wide, we use them for front-end application development, backend apps, building databases, and even in machine learning and AI with the support of other libraries.
Let me quickly point out some simple but effective ways that could help you write better and more readable code in Javascript.
Const vs Let:
In Javascript, there are multiple ways in which you can declare and use variables, in the older days we used to declare variables using ‘var’, but this had its own problems like mutations, scoping, and other things. Later when ES6 was introduced we got two new ways to declare and use variables i.e. ‘ const’ and ‘let’. But which one should we use?
Simply said always stick to ‘const’, but if you have a case where you may override or reassign the value of the variable then you can use ‘let’. Sticking to this rule ensures that the values are not mutated and results in predictable behavior.
// Let allows variable value to be re-assigned
let marks = 90;
marks = 100;
console.log(marks); // prints 100;
const marks = 30;
marks = 100; // Throws error as we can't re-assign the values of a const
Optional Chaining
Disclaimer: This feature is only available from Node.js 14+, check the compatibility before using this in your code.
This is one of the features which lets you write less & readable code when you want to safely access nodes within an object and avoid null pointer exceptions.
For example, let’s say you have a nested object and you are accessing the last child node of the object. Usually, when we traverse through that object you might validate the presence of each node before accessing its child node like the one below.
const developer = {
name: 'Adam',
address: {
state: 'CA',
},
};
const state = developer && developer.address && developer.address.state;
But with Optional Chaining, we could write the above code much easier.
const developer = {
name: 'Adam',
address: {
state: 'CA',
},
};
// using optional chaining.
const state = developer?.address?.state;
Switch Case instead of multiple IF-ELSE
Traditionally we will be writing any conditional statements using the if-else and this is totally fine, but the problem comes when you have multiple if-else-if statements within the function.
let city = '';
if (location === 'NY') {
city = 'New York';
} else if (marks === 'LA') {
city = 'Los Angeles';
} else if (marks === 'CA') {
city = 'California';
}
In this case, we could use the Switch case instead of an if-else-if statement, generally, it is recommended to use the switch case when you have more than 3 if-else-if statements, and this is purely for readability.
switch (shortForm) {
case 'NY':
city = 'New York';
break;
case 'LA':
city = 'Los Angeles';
break;
case 'CA':
city = 'California';
break;
default:
};
Sometimes it’s even better to use maps instead of switch case statements like below.
const cities = {
NY: 'New York',
LA: 'Los Angeles',
CA: 'California',
};
console.log(cities.NY) // prints "New York"
Ternary And Short-Circuiting
Another way to write single-line, readable conditional codes is to use the Ternary operator or the Short circuiting operator in Javascript.
// Using Ternary Operator.
const category = marks >= 80 ? 'Distinction' : 'Average';
// Using Short circuiting ( && || ) operator
const category = (marks >= 80 && 'Distinction') || 'Average';
// Using if-else
let category = 'Average';
if (marks >= 80) {
category = 'Distinction';
}
Conditionally Adding Keys To Object
Normally if we want to add a new key to an object we would do something like Object.key (MyObject.newKey = value), and if we want to conditionally add a key then we would use the if-else statements, but this would become messy if you have multiple keys that need to be added and each based on different conditions. We can resolve this by using the spread operator in Javascript as well.
// Using if-else to add keys to the object
const developer = {
name: 'John',
techStack: 'Node.js',
};
if (data?.address?.length > 0) {
developer.address = 'CA';
}
// Using spread operator.
const developer = {
name: 'Adam',
techStack: 'c#',
...(data?.address?.length && { address: 'CA' })
};
Strict Equality validation (=== vs ==)
This is again another common mistake that we developers make while writing code. Both Triple equals and double equals might seem to be doing the same thing, but it’s not. Never use a double equal in javascript, always use the tripel equals(===) because double equal does not check the type of the values while checking the equality, but triple equal always check equality along with the type of the values. The same goes for the “not-equal” operators as well.
const LHS = true;
const RHS = '1';
if (LHS == RHS) console.log('Both are equal') // prints the statement
// prints nothing as LHS is of type Boolean and RHS is of type String
if (LHS === RHS) console.log('Both are equal')
0 == ""; // true
1 == "1"; // true
1 == true; // true
0 === ""; // false
1 === "1"; // false
1 === true; // false
Object Destructuring:
Using object restructuring we can avoid the multi-line variable declarations and can simply extract values from objects and declare them in variables in a single line like below.
// Our object
const developer = {
name: 'Andrew',
experience: 30,
techStack: 'Node.js',
}
// Traditional way
const name = developer.name;
const experience = developer.experience;
const techStack = developer.techStack;
// Using object destructuring
const { name, expericence, teckStack } = developer;
Proper Linting rules
This is again an important thing that you have to set up in your project, this would definitely help in following a common coding standard across developers. We could enforce this in multiple ways.
- If you are using a VS-Code IDE then you can add this as an extension and that will show you warnings based on the ES lint rules that you can specify in your application using the .eslintrc.json file
Ref: https://eslint.org/ - Also, you can set this as a pre-commit hook using tools like Husky and Lint-staged(npm modules). Creating a pre-commit hook ensures that the developer will only be able to create a commit only when all the ES lint rules have been satisfied.
Trailing Commas
This is again a debatable topic some people prefer adding trailing commas while creating objects, and some don’t but I personally prefer using trailing commas, because they highly help me in PR reviews. Let's say you have multiple keys in an object and you don’t have a trailing comma at the last. Later you want to add additional keys now, in this case, you will be adding the comma to the last added key and then will start adding new keys, now if you take this from a GitHub perspective since you have added a comma to the previous key it will consider that you have modified that line and will show that as a change in GitHub, this might not seem to be a problem for simple objects, but in the longer run when the application grows and you have functions exported instead of simple keys this would make sense.
In addition to the above, we could follow the below which is general for any language.
- Having modular components and dedicating a single task to a function will help a lot in terms of unit testing.
- Adding proper comments to your code blocks, but never overdo it.
- Following the DRY(Don’t repeat yourself) principle and re-use as many functions as possible.
- Add unit-test cases to your functions and ensure both positive and negative cases are covered.
- Provide proper naming to your variables, and avoid names like x, y, and value1. Always provide readable and brief variable names.
- Avoid circular dependency among files.
Happy coding 👍