Top 10 JavaScript Tips Every Developer Should Know by Heart!

Hey fellow coders! Are you ready to take your JavaScript game to the next level?

In this article, we’re diving into some essential JavaScript tips and tricks, including JavaScript best practices that every developer should know. Whether you’re a newbie eager to upskill or a seasoned pro looking for some fresh hacks, these JavaScript tips and tricks will elevate your coding game.
So, pull up a coding chair, grab your favourite cup of coffee, and let’s dive into the amazing world of JavaScript Tips together!

Ready for a coding adventure?

Let’s get started!

1. Use JavaScript Promise.all() instead of await

Javascript Tips - Geekypassion

This is more likely to say that we should not wait for execution time. For example, if we want to make two database call to fetch data, we would have to wait for each execution.

const getUsers = async () => {
    const customers = await findAllCustomers();
    const admins = await findAllAdmins();
    const totalUsers = await countTotalUsers();

    return { customers, admins, totalUsers }
}

Instead, We can run both calls in parallel to reduce execution time by half of the time. This technique is a game-changer for enhancing your coding efficiency with JavaScript Tips.

const getUsers = async () => {
    const customers = findAllCustomers();
    const admins = findAllAdmins();
    const totalUsers = countTotalUsers();

    return Promise.all([customers, admins,totalUsers]);
}

By leveraging Javascript Promise.all(), you allow each item to be processed simultaneously, significantly improving the overall performance and responsiveness of your application.

2. Merge arrays without causing server load

Whenever you have the requirement to merge large arrays.

let array1 = [1, 2, 3];
let array2 = [4, 5, 6];
console.log(array1.concat(array2)); // [1,2,3,4,5,6];

Use of JavaScript Array.concat() works fine with small arrays.

But, To merge large arrays we use

Array.push.apply(arr1, arr2);
let array1 = [1, 2, 3]; 
let array2 = [4, 5, 6]; 
console.log(array1.push.apply(array1, array2)); // [1,2,3,4,5,6];

Reason for not using JavaScript Array.concat() on large arrays, it consumes a lot of server memory, whereas it creates a separate new array. It will also optimize your JavaScript code performance. Utilizing these JavaScript best practices is crucial for efficient array operations.

3. Simplify Code and Enhance Performance with JavaScript Object Mapping

Let’s dive into another scenario where you can boost your code’s efficiency using object mapping. Consider a situation where you need to determine a discount based on a customer’s loyalty level.

Here’s the traditional if-else approach:

function calculateDiscount(loyaltyLevel) {
    console.time('if else time');
    if (loyaltyLevel === 'GOLD') {
        applyGoldDiscount();
    } else if (loyaltyLevel === 'SILVER') {
        applySilverDiscount();
    } else if (loyaltyLevel === 'BRONZE') {
        applyBronzeDiscount();
    }
    console.timeEnd('if else time');
}

Or using a switch statement:

function calculateDiscount(loyaltyLevel) {
    console.time('switch time');
    switch (loyaltyLevel) {
        case 'GOLD':
            applyGoldDiscount();
            break;
        case 'SILVER':
            applySilverDiscount();
            break;
        case 'BRONZE':
            applyBronzeDiscount();
            break;
    }
    console.timeEnd('switch time');
}

Now, let’s embrace the simplicity of object mapping:

function calculateDiscount(loyaltyLevel) {
    console.time('object time');
    const discountMap = {
        'GOLD': applyGoldDiscount,
        'SILVER': applySilverDiscount,
        'BRONZE': applyBronzeDiscount
    };
    discountMap[loyaltyLevel] && discountMap[loyaltyLevel]();
    console.timeEnd('object time');
}

the object mapping approach offers a more concise and readable solution, with a noticeable improvement in execution time.

  • calculateDiscount(‘SILVER’) took if else time: 2.45ms
  • calculateDiscount(‘SILVER’) took switch time: 0.14ms
  • calculateDiscount(‘SILVER’) took object time: 0.13ms

By adopting object mapping, you simplify your code while ensuring optimal performance. Embrace this technique to make your code more elegant and efficient.

4. Replace Array Duplicates with JavaScript Set() for Unique Elements

When dealing with unique values in JavaScript, the Set() object proves to be a powerful ally. Let’s explore how you can leverage Set() to enhance the efficiency of your code.

Consider a scenario where you have an array of numbers, and you want to filter out duplicate values. Traditionally, you might use loops and conditional checks, but there’s a more elegant solution with Set().

function removeDuplicates(arr) {
    console.time('array time');
    const uniqueArray = [];
    for (const item of arr) {
        if (!uniqueArray.includes(item)) {
            uniqueArray.push(item);
        }
    }
    console.timeEnd('array time');
    return uniqueArray;
}

Instead, opt for the Set() approach:

function removeDuplicates(arr) {
    console.time('set time');
    const uniqueSet = new Set(arr);
    const uniqueArray = [...uniqueSet];
    console.timeEnd('set time');
    return uniqueArray;
}

Using Set() simplifies the process by automatically eliminating duplicates. The execution time speaks for itself:

  • removeDuplicates([1, 2, 2, 3, 4, 4, 5]) took array time: 0.27ms
  • removeDuplicates([1, 2, 2, 3, 4, 4, 5]) took set time: 0.05ms

By embracing Set(), you not only achieve cleaner code but also improve the speed of unique value extraction.

5. Transform Callback Functions into JavaScript Promises

Managing asynchronous operations in JavaScript can be challenging, especially with traditional callback-based functions. However, there’s a cleaner and more modern approach using util.promisify. Let’s explore how to upgrade your asynchronous code for improved readability and simplicity.

Consider a scenario where you have a callback-based function waiting for a specified time:

const util = require('util');

// Traditional callback-based function
function waitForSomeTime(callback) {
    setTimeout(() => {
        console.log('Time is up!');
        callback(null, 'Done!');
    }, 2000);
}

Now, transform this into a promise using util.promisify:

// Promisified version using util.promisify
const waitForSomeTimeAsync = util.promisify(waitForSomeTime);

With this transformation, you can now use async/await for cleaner asynchronous code:

// Using async/await with the promisified function
async function asyncOperation() {
    try {
        console.log('Waiting for some time...');
        const result = await waitForSomeTimeAsync();
        console.log(result);
    } catch (error) {
        console.error('Error:', error);
    }
}

asyncOperation();

This approach simplifies the flow, making it more readable and maintaining error handling through the try-catch mechanism. As a result:

  • asyncOperation() prints ‘Waiting for some time…’
  • After 2 seconds, ‘Time is up!’ is logged, and ‘Done!’ is printed.

By upgrading callback functions to promises, you enhance the clarity of your asynchronous code and embrace a more modern JavaScript development style.

6. Multiple Checks with JavaScript Array.includes()

When working with arrays in JavaScript, checking if an element exists within the array is a common task. Instead of using multiple conditional statements, leverage the power of Array.includes() for a cleaner and more efficient approach.

Consider a scenario where you need to check if a value exists in an array:

function checkMembership(value) {
    const array = [1, 2, 3, 4, 5];

    if (value === 1 || value === 3 || value === 5) {
        console.log('Value exists in the array!');
    } else {
        console.log('Value does not exist in the array!');
    }
}

Rather than using multiple === comparisons, utilize Array.includes():

function checkMembership(value) {
    const array = [1, 2, 3, 4, 5];

    if (array.includes(value)) {
        console.log('Value exists in the array!');
    } else {
        console.log('Value does not exist in the array!');
    }
}

This approach is not only more concise but also easier to read. You can perform the same check with less code, making it more maintainable and scalable.

checkMembership(3); // Outputs: Value exists in the array!
checkMembership(7); // Outputs: Value does not exist in the array!

By embracing Array.includes(), you enhance the efficiency of your array membership checks and create more readable code. Upgrade your array operations for a cleaner and streamlined JavaScript development experience.

7. Implement Caching for Efficient Data Retrieval

Efficiently managing data retrieval is crucial for optimal performance. In JavaScript, you can enhance your code by incorporating a simple caching mechanism to avoid unnecessary duplicate calls. Let’s explore how to implement and benefit from caching in database functions.

Consider a scenario where you have a database function with a caching mechanism:

function dataFunction() {
    const data = {
        101: { id: 101, product: 'Laptop' },
        202: { id: 202, product: 'Smartphone' },
        // ... more sample data ...
    };

    const cache = {};

    return {
        get: function (id) {
            if (id in cache) {
                return cache[id];
            } else {
                const result = data[id];
                cache[id] = result;

                // Limit the cache size to prevent memory leaks
                const cacheKeys = Object.keys(cache);
                if (cacheKeys.length > 5) {
                    const oldestKey = cacheKeys.shift();
                    delete cache[oldestKey];
                }

                return result;
            }
        },
    };
}

const myData = dataFunction();

console.log(myData.get(1)); // Retrieves and caches data for id 1
console.log(myData.get(2)); // Retrieves and caches data for id 2
console.log(myData.get(1)); // Retrieves data for id 1 from cache
console.log(myData.get(3)); // Retrieves and caches data for id 3, removing oldest entry in the cache

In this example, the dataFunction function returns an object with a get method that efficiently retrieves and caches data. The cache size is limited to prevent memory leaks.

Implementing a caching mechanism not only minimizes redundant data fetching but also significantly improves the performance and memory management of your applications, following the best practices in Javascript development. Consider integrating caching into your database functions for a more responsive and resource-efficient codebase.

8. Simplify Object Assignment with Destructuring

Destructuring in JavaScript is a powerful feature that allows you to extract values from objects or arrays effortlessly. Whether it’s simplifying object assignment or handling function parameters more elegantly, destructuring can significantly enhance your code. Let’s explore a practical tip to leverage destructuring effectively.

Consider a scenario where you have an object representing a user:

const user = {
    firstName: 'John',
    lastName: 'Doe',
    age: 30,
    country: 'USA',
};

Traditionally, you might assign these properties individually:

const firstName = user.firstName;
const lastName = user.lastName;
const age = user.age;
const country = user.country;

console.log(firstName, lastName, age, country); // Outputs: John Doe 30 USA

This concise syntax allows you to declare and assign variables in a single line, making your code cleaner and more readable.

By embracing object destructuring, you streamline your code, making it more concise and expressive. Whether it’s assigning variables or handling function parameters, leverage destructuring to enhance the readability and maintainability of your JavaScript code.

9. Flatten Multi-dimensional Arrays with Array.flat() and Infinity

JavaScript’s Array.flat() method is a powerful tool for flattening nested arrays, making your code more concise and readable. By leveraging the Infinity parameter, you can flatten arrays of any depth with a single method call. Let’s explore how to use Array.flat() effectively with the Infinity parameter.

Consider a scenario where you have a nested array:

const nestedArray = [1, [2, [3, [4, 5]]], 6];

Traditionally, flattening such an array involves using nested concat or reduce methods:

const flattenedArray = [].concat(...nestedArray);
console.log(flattenedArray); // Outputs: [1, 2, [3, [4, 5]], 6]

Instead, simplify the process using Array.flat() with the Infinity parameter:

const flattenedArray = nestedArray.flat(Infinity);
console.log(flattenedArray); // Outputs: [1, 2, 3, 4, 5, 6]

This approach ensures that all levels of nesting are flattened, regardless of the array’s depth. The use of Infinity simplifies the code and makes it more robust when dealing with deeply nested structures.

By incorporating Array.flat() with Infinity, you streamline the process of flattening nested arrays, making your code more elegant and flexible. Embrace this tip to simplify multi-dimensional array handling in JavaScript.

10. Simplify Data Filtering with Curried Functions

Currying is a functional programming technique that allows you to transform a function with multiple parameters into a series of functions with a single parameter. This technique can lead to cleaner and more flexible code. Let’s explore how currying can simplify data filtering in JavaScript.

Consider a scenario where you have a data filtering function without currying:

// Without currying
const filterWithoutCurry = (data, criteria) => {
    return data.filter(item => item > criteria);
};

And here’s how you would use it:

const dataSet = [2, 8, 6, 12, 3, 15];

console.log(filterWithoutCurry(dataSet, 5));  // Traditional function call
console.log(filterWithoutCurry(dataSet, 10)); // Traditional function call

Now, introduce currying to create a more flexible and reusable function:

// With currying
const dataFilterWithCurry = (data) => (criteria) => {
    return data.filter(item => item > criteria);
};

const curryFilter = dataFilterWithCurry(dataSet);
console.log(curryFilter(5));  // Curried function call
console.log(curryFilter(10)); // Curried function call

With the curried function, you can partially apply arguments, creating a new function that is specialized for a particular filtering criteria. This enhances code flexibility and encourages reuse.

Benefits of Currying:

  1. Partial Application: You can create specialized functions by applying some of the arguments, making your code more modular.
  2. Code Reusability: Currying promotes the reuse of functions for different scenarios, reducing redundancy in your code.
  3. Readability: The curried syntax often leads to more readable code, especially when dealing with multiple parameters.

Incorporating currying into your JavaScript functions simplifies your code, increases flexibility, and creates more modular and reusable components. Consider adopting this technique for scenarios where partial application and code reuse can enhance your development process with effective Javascript Tips.

Conclusion

In conclusion, mastering these JavaScript tips empowers developers to write cleaner, more efficient code. Leveraging features like async/await, object mapping, destructuring, spread/rest operators, and currying enhances code readability, simplifies complex tasks, and promotes a more elegant and streamlined approach to JavaScript development.

Thanks for reading. I hope you enjoy it! Happy coding!

Read More: How to hot reload Docker container using Docker Volume

Leave a Comment