15 JavaScript Tips You Can't Afford to Miss

·

10 min read

After mastering how to write JavaScript code, the next step is advancing to practice —— how to truly solve problems. We need to refactor JS code to make it simpler and more readable because such programs are easier for team members to collaborate closely.

Today, we'll introduce 15 best practice techniques to help simplify JavaScript code, making it easier for other developers to understand, and enhancing its readability and maintainability.

1.Declare and initialize variables at the top

Nothing disrupts readability more than delayed declarations. Just as preparing all tools before starting work can simplify the process, declaring all variables before diving into the details of a function can make the program simpler. This also makes it easier for us to adjust variable names or values later on.

When it comes to variables, the best practice is to initialize them upon creation so that you and your team can ensure there are no undefined variables.

<script>
var x = 5;
</script>

2.Build modular, specialized functions

For efficiency and readability, having a single function to handle everything is impractical. Therefore, when designing functions, adhere to the principle of one task per function. Function naming should also match the task.

Is this making it easier for others to read the code? Because dealing with only one task naturally makes functions simpler. Moreover, if needed, you and your team can apply this function to other programs in the future.

Consider the following example. With the improved code, you can clearly understand the purpose of each task just by looking at the function and variable names.

function table(columns, rows, item){
creates table and searches it for the passed item
}

// compared to

function createTable(columns, rows){
//creates table
}

function searchTable(table.length, item) {
//searches table for the passed item
}

3.Identify and remove duplicate code

Sometimes, duplicate lines of code are unavoidable. In such cases, refactor the duplicate code into a function and replace all instances where the code was used with calls to the function.

This not only reduces visual clutter but also aids in debugging in the future, as the team only needs to look at the function rather than checking multiple places in the code.

<script>
var x = 5;
var y = 6;
var x = x*2
var y = y*2
</script>

<script>
var x = 5;
var y = 6;

function double(value){
return value*2;
}
double(x);
double(y);
</script>

4.Comment generously

Comments are a great way to summarize the purpose of code snippets, saving other developers the time it would take to figure out what the code is supposed to do on their own.

If the code lacks comments describing what tasks it's supposed to accomplish, potential errors can be caught early. In general, it's best to have a comment for each function.

Not sure if you should write a comment? Go ahead and do it! If it becomes too cluttered, you can always remove them later.

//declares and initializes var x
<script>
var x = 5;
</script>

5.Beware of excessive recursion

Note: Avoid nesting recursion functions too deeply. While multiple levels of nesting may solve many problems at once, it can be difficult to follow at a glance.

To avoid confusion, liberate nested recursive functions whenever possible without incurring significant runtime costs. If you have nested functions with 3 or more layers, your colleagues might have difficulty following your train of thought.

<script>
function function1(a, b){
  function function2(){
    function function3(){
    //this is too hard to follow and can likely be solved another way
    }
  }
}
</script>

6.Efficiently manipulate the DOM

Accessing the DOM is crucial for fully utilizing a program, but doing so repeatedly can lead to visual clutter and slow down the program.

Therefore, it's best to access the DOM once and cache it in a variable for later use. Then, when needed, access the variable directly rather than accessing the DOM. This process is visually cleaner and more efficient.

Note: The best practice is to use the $ symbol to denote DOM references.

function accountInfo(){
var email = $("#accounts").find(".email").val();
var accountNumber = $("#accounts").find(".accountNumber").val();
}

// Contents cached to variable "accounts"

function accountInfo(){ var $accounts = $("#accounts"); 
var name = $accounts.find(".email").val(); 
var age = $accounts.find(".accountNumber").val();
}

7.Avoid global variables at all costs

In JavaScript, variables have either global or local scope. Scope determines where variables are defined and accessed in the code. We can define global variables anywhere in the program, even outside functions. Local variables are used only within the functions where they are defined.

If there are local variables and global variables with the same name, JavaScript will prioritize the local variables and ignore the global variables. We should avoid using global variables because they may unintentionally override window variables, leading to errors.

Moreover, excessive global variables can slow down the program because global variables are not deleted until the window is closed, whereas local variables are deleted after the function completes.

<html>
      <script>
            var myVar = "my global variable"; // This variable is declared as global
            function localVariable( ) {
               var myVar = "my local variable";  // This is a locally declared variable
      </script>
   </body>
</html>

8.Use shorthand notation (object literals)

When designing objects or arrays in JavaScript, you can save space by choosing shorthand notation. This is achieved by setting the properties of objects or arrays during declaration rather than afterward.

This way, we don't have to keep track of which object or array is being set on each line, making this part of the code easier to read. While it's a small change, as objects and arrays become more complex, it can definitely save your team a lot of time.

For example, creating an object:

Normal notation:

var computer = new Object();
    computer.caseColor = 'black';
    computer.brand = 'Dell';
    computer.value = 1200;
    computer.onSale = true;

Shorthand notation:

var computer = {
    caseColor: 'black',
    brand: 'Dell',
    value: 1200,
    onSale: true
};

Shorthand array:

var computerBrands = [
    'Dell',
    'Apple',
    'Lenovo',
    'HP',
    'Toshiba',
    'Sony'
];

9.Use strict mode to catch silent errors

Compared to other programming languages like C++ and Java, JavaScript is a very lenient language in terms of syntax. While this leniency helps to run code without triggering errors, it can lead to silent errors. Therefore, we need to address these hidden silent errors; otherwise, unexpected behaviors may occur.

The solution is strict mode. It includes two main changes:

  • Previously silent errors by the compiler now throw errors

  • Errors that prevent JavaScript from optimizing code are fixed

  • JavaScript Strict Code programs typically run faster than non-strict mode programs.

Either add 'use strict'; at the top of the script section or before the desired functionality (partial strict).

10.Set default values

When creating objects, you can set default values for some or all properties of the object. This ensures that each property has a value that is not undefined and also declares the data type required for the property. Additionally, by not setting default values for certain properties, you can communicate to the team that these values are not needed for the object to function normally.

function logProperty({
    address = '111 11th Street, 11111', 
    unit,   //optional
    landlord = 'Sara', 
    tenant = 'Raj', 
    rent = 500, 
})

In the above code, the unit property is optional, but the other four properties (expected data types) must have default values. Therefore, the unit is left blank.

11.Use template literals to concatenate strings

String concatenation can be cumbersome, especially when combining strings and variables. We can simplify the concatenation process using template literals (marked with backticks), as template literals accept both strings and variables.

function greet(name) {
    return `Hi, ${name}`; //template literal
}
console.log(greet('Leo'));

Note that by using template literals, we can greet the user based on the name passed, combining the string 'Hi' with the value of the name variable. Thus, this code prints: Hi, Leo

12.Use includes() for existence testing

Testing for the existence of a value in an array is a common problem. Fortunately, JavaScript has a special array method, includes(), which returns a boolean value if the array contains the search value. This is an efficient and readable solution without the need to search the array.

const sections = ['contact', 'shipping'];

function displayShipping(sections) {
    return sections.includes('shipping');
}

console.log(displayShipping(sections));

Additionally, there is the indexOf() method that can be used to check the value and find the index.

13.Shorten conditions with falsy values

In JavaScript's type coercion, there are values that are equivalent to false, including:

  • Boolean false

  • null

  • 0

  • NaN

  • ' '

  • " "

In JavaScript, equivalence with == means two objects share the same value, but they may not be the same type. Identical === means two objects share the same type and value. What's the use of this?

Well, instead of creating separate variables to store boolean values, why not use the above values as default values to report false if nothing overrides them. For example, you need to check if a given employee has received equipment training (equipmentTraining). This machine only requires the lowest level of training, and the level of training is not important.

Therefore, we check if equipmentTraining has afalsy value, i.e., the default value of ''. If so, execute the if statement and return that the employee is not authorized. If equipmentTraining contains any string other than the default value, it indicates a truthy value, so the if statement is not executed.

const employee = {
    name: 'Eric',
    equipmentTraining: '',
}

if (!employee.equipmentTraining) {
    console.log('Not authorized to operate machinery');
}

14.Share methods through inheritance

Inheritance involves sharing properties or methods between classes. The example below uses the super keyword to achieve inheritance, allowing the constructor in FlashCoupon to access the parent constructor in Coupon. Defining methods only once (in the parent class) enhances the readability of the code. The code also becomes more modular because the inheritor class can be specifically used for a given task.

Note that the code block at the top establishes the parent class Coupon, whose properties and methods are shared with FlashCoupon, as seen when FlashCoupon calls the getExpirationMessage method on its last line.

class Coupon {
  constructor(price, expiration) {
    this.price = price;
    this.expiration = expiration || 'Two Weeks';
  }
  getExpirationMessage() {
    return `This offer expires in ${this.expiration}`;
  }
}
export default Coupon;



-----------



import Coupon from './extend';

class FlashCoupon extends Coupon {
    constructor(price, expiration) {
        super(price);
        this.expiration = expiration || 'two hours';
    }
}

const flash = new FlashCoupon(10);
console.log(flash.getExpirationMessage());

15.Write shorter loops using array methods

The final tip delves into the complexity of array optimization. Looping is a common method for creating and populating arrays. However, loops can result in cluttered and hard-to-read code.

Therefore, we can use array methods to achieve similar effects, such as for loops in just a few lines of code. Take the following for loop as an example.

const prices = ['1.0', 'negotiable', '2.15'];

const formattedPrices = [];
for (let i = 0; i < prices.length; i++) {
    const price = parseFloat(prices[i]);
    if (price) {
        formattedPrices.push(price);
    }
}
console.log(formattedPrices);

We can achieve the same result with just three lines using the map method. This method creates an array of equal size, with only the price property. Then, parseFloat is used to obtain the floating point value of the price.

const prices = ['1.0', '2.15'];
const formattedPrices = prices.map(price => parseFloat(price));
console.log(formattedPrices);

Summary

Optimizing JavaScript programming continuously pursues conciseness and readability. From variable declaration to function design, repetitive code to DOM manipulation, error handling to array looping, adhering to best practices can make code easier to understand and maintain. By practicing these techniques, teams can improve efficiency, reduce errors, and collaborate better in development.

Learn more: