JavaScript Documentation Guidelines - Entropic-Visio/SWE-Pioneers GitHub Wiki

The purpose of this documentation is to act as a guide, leading you through the complex world of JavaScript, and offering valuable tips, techniques, and established approaches to enhance your coding abilities. Whether you are an experienced programmer looking to improve your expertise or a beginner wanting to build a solid understanding, this resource is essential for opening doors to JavaScript development. This will include:

  • Code Quality: Enhance the overall quality of the code, making it more readable, maintainable, and less prone to errors.

  • Consistency: Ensure a consistent coding style across the project and the team, promoting collaboration and making it easier for developers to understand and contribute to the codebase.

  • Performance: Optimise code for better performance, reducing execution times and improving the efficiency of the application.

  • Security: Mitigate potential security vulnerabilities by following secure coding practices, protecting the applications from common threats.

  • Scalability: Design code in a way that allows for easy scalability, accommodating future changes or additions to the codebase.

  • Documentation: Maintain clear and comprehensive documentation to aid understanding, troubleshooting, and collaboration among developers.

  • Debugging: Facilitate debugging and error identification by adhering to best practices, making it easier to isolate and fix issues in the code.

  • Compatibility: Write code that is compatible with various browsers and environments, ensuring a consistent experience for users across different platforms.

By leveraging the insights and strategies provided in this guide, developers can elevate their skills and create more efficient and effective JavaScript applications.

Best Practices for JavaScript

1. Adopting a consistent coding style

Adopting a consistent style is important as it contributes to better collaboration, easier maintenance, and improved code quality, resulting in more efficient and error-resistant development processes. [1]

// Poorly named variables:
let a = 'John';
let fn = () => console.log('Hello');

// Descriptive named variables:
let firstName = 'John';
let sayHello = () => console.log('Hello');

2. Naming Variables and Functions

Making appropriate variable declarations is one of the core JavaScript best practices. It is advisable to use let and const rather than var because let supports block scoping, which restricts the variables' scope to the closest enclosing block, and const guarantees that a variable will not be reassigned. Also, the standard is to use camel-case for variables and functions (like myVariableName), and Pascal case for classes (like MyClassName). [2]

// DON'T
let fName, lName
let cntr

let full = false
if (cart.size > 100) {
  full = true
}

// DO
let firstName, lastName
let counter

const MAX_CART_SIZE = 100
// ...
const isFull = cart.size > MAX_CART_SIZE

3. Commenting the Code

It is super important to comment on code so everyone can understand it. Comments explain what the code is supposed to do and why it is written that way, which makes it easier for developers to work with. They also help to clarify complicated parts and act as a kind of instruction manual for now and later. Plus, comments can point out things that need fixing or doing later, which stops confusion and makes teamwork easier. But it is crucial to find the right number of comments, so the code does not get too messy and stays easy to read.

/**
* Represents a book.
* @constructor
* @param {string} title - The title of the book.
* @param {string} author - The author of the book.
*/
function Book(title, author) { … }

4. Avoid Global Variables

When writing JavaScript code, it is best to avoid using global variables as they can cause naming conflicts, use up more memory, and make the code harder to maintain. Instead, focus on encapsulation and modularisation to keep things tidy. [3]

You can use module systems like CommonJS or ES modules to organise your code into reusable and maintainable modules, which will help prevent cluttering the global namespace and make your code easier to manage. So, keep those global variables to a minimum and embrace encapsulation and modularisation for cleaner and more efficient JavaScript code.

// CommonJS module
// math.js
const add = (a, b) => a + b;
const subtract = (a, b) => a - b;
module.exports = { add, subtract };
// main.js
const { add, subtract } = require('./math.js');
console.log(add(5, 3)); // Output: 8
console.log(subtract(7, 2)); // Output: 5

5. Use Error Handling

It is super important to handle errors properly when writing JavaScript code. If you do it right, you can stop your app from crashing, make things better for users, and make it easier to find and fix bugs. Here is what you should do:

Use try-catch blocks to catch and deal with exceptions. Put code that might cause errors inside try blocks and then handle those errors in catch blocks. [3]

try {
  // Potentially error-prone code
  const result = calculateSomething();
  console.log(result);
} catch (error) {
  // Handle the error
  console.error('An error occurred:', error);
}

Also, make sure you have good error logging in place. This means using logging libraries or setting up your error logging system to keep track of and understand any errors that happen in your app.

function logError(error) {
  // Send the error to a logging service or perform custom logging
  console.error('Error:', error);
}
try {
  // Code that may throw an error
} catch (error) {
  logError(error);
}

6. Efficient Data Structures and Algorithms

While it is true that choosing the right data structures and algorithms can impact the performance of JavaScript code, it is important to consider that prioritizing efficiency can sometimes lead to overly complex and difficult-to-maintain code. In some cases, the trade-off between performance and readability may not be worth it, especially in smaller-scale projects or when working in a team environment where code clarity is crucial. Here are some practical uses to consider: [3]

Make sure to use the right data structures for your code needs, like arrays for indexed access or stacks for LIFO operations. Also, use objects or maps for key-value pair lookups and sets for unique values.

// Good: Using an array for indexed access
const numbers = [1, 2, 3, 4, 5];
const thirdNumber = numbers[2];

// Good: Using a map for key-value pair lookups
const userMap = new Map();
userMap.set('John', { age: 30, email: '[email protected]' });
const john = userMap.get('John');

It is important to have efficient algorithms for common tasks, such as searching, sorting, and data manipulation. For example, use binary search for sorted arrays, quicksort, or merge sort for sorting, and optimize data manipulation to minimize unnecessary iterations. It is all about using the right tools for the job and making sure everything runs smoothly. Just keep in mind the specific requirements and choose the best options accordingly.

// Good: Using binary search for efficient searching
function binarySearch(array, target) {
  let start = 0;
  let end = array.length - 1;
while (start <= end) {
    const mid = Math.floor((start + end) / 2);
    if (array[mid] === target) {
      return mid;
    } else if (array[mid] < target) {
      start = mid + 1;
    } else {
      end = mid - 1;
    }
  }
  return -1;
}

7. Optimise Loops

In JavaScript, loops are commonly used to go through arrays, objects, and other data structures. But if you are not careful, looping can slow things down, especially with big sets of data. To make loops work better, try these tips: [4]

Use a for loop instead of a for…in loop for arrays. The for loop is faster and skips inherited properties.

// Good
const numbers = [1, 2, 3, 4, 5];
for (let i = 0; i < numbers.length; i++) {
  // Do something with numbers[i]
}
// Bad
const numbers = [1, 2, 3, 4, 5];
for (const index in numbers) {
  // Do something with numbers[index]
}

Cache the array length before the loop to avoid constantly checking the length property.

// Good
const numbers = [1, 2, 3, 4, 5];
const length = numbers.length;
for (let i = 0; i < length; i++) {
  // Do something with numbers[i]
}

// Bad
const numbers = [1, 2, 3, 4, 5];
for (let i = 0; i < numbers.length; i++) {
  // Do something with numbers[i]
}

Think about using array iteration methods like forEach, map, and filter for clearer, shorter code. So, if you want your loops to work better, try these tricks.

const numbers = [1, 2, 3, 4, 5];
// Good
numbers.forEach((number) => {
  // Do something with number
});

// Bad
for (let i = 0; i < numbers.length; i++) {
  const number = numbers[i];
  // Do something with number
}

References

[1] “Write better code by following these JavaScript best practices,” Dawson Codes, May 18, 2023. https://www.dawsoncodes.com/posts/10/write-better-code-by-following-these-javascript-best-practices

[2] R. Engineering, “JavaScript Clean Coding Best Practices - RisingStack Engineering,” RisingStack Engineering, Dec. 13, 2016. https://blog.risingstack.com/javascript-clean-coding-best-practices-node-js-at-scale/

[3] Shahmeer, “Best Practices for Writing Efficient JavaScript Code,” Medium, May 13, 2023. https://medium.com/@ishahmeer/best-practices-for-writing-efficient-javascript-code-90689033c6f6

[4] “Best Practices for Writing Efficient JavaScript Code,” DEV Community, May 13, 2023. https://dev.to/codewithshahmeer/best-practices-for-writing-efficient-javascript-code-160p