Front end practice: Top 25+ Javascript code best practices for development
Tags: webdev, javascript, beginners, tutorial
Published: 2023-07-31 04:30:00

In a [previous article](https://lakshmananarumugam.com/front-end-practice-css-and-scss), I covered front-end best practices in CSS/SCSS. This article will share the basic javascript best practices for development

Frontend development in JavaScript involves creating user interfaces and handling the presentation layer of web applications. Here are some best practices to follow, along with examples, to ensure a clean and maintainable codebase:

**1.Modularization**: Break down your code into smaller, reusable modules. This enhances code readability and makes it easier to manage dependencies.

Example:

```javascript
// users.js (module)
export function getUsers() {
  // Fetch users from the API or data source
}

// main.js (entry point)
import { getUsers } from './users.js';

getUsers();
```

**2.Use const and let**: Prefer `const` for variables that won't be reassigned and `let` for variables that will change.

Example:

```javascript
const PI = 3.14159;
let count = 0;

count = 10; // Valid
PI = 3; // Error
```

**3.Avoid global variables**: Minimize the use of global variables to prevent polluting the global scope and potential conflicts.

Example:

```javascript
// Avoid this
let globalVar = 'I am global';

function someFunction() {
  // ...
}

// Use this instead
(function() {
  let localVar = 'I am local';

  function someFunction() {
    // ...
  }
})();
```

**4.Use arrow functions**: Arrow functions provide concise syntax and maintain the lexical `this` value, reducing the need for `bind()`.

Example:

```javascript
// Regular function
function add(a, b) {
  return a + b;
}

// Arrow function
const add = (a, b) => a + b;
```

**5.Avoid polluting the global namespace**: Encapsulate your code within a module or an IIFE (Immediately Invoked Function Expression) to avoid global namespace pollution.

Example:

```javascript
// Instead of
function myFunction() {
  // ...
}

// Use this
(function() {
  function myFunction() {
    // ...
  }

  // Call the function or attach it to the desired scope
  myFunction();
})();
```

**6.Use modern ES6+ features**: Embrace ES6+ features like destructuring, spread syntax, and template literals to write more concise and expressive code.

Example:

```javascript
// Destructuring
const { firstName, lastName } = user;

// Spread syntax
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const combinedArray = [...arr1, ...arr2];

// Template literals
const name = `My name is ${firstName} ${lastName}.`;
```

**7.Avoid inline styles and use CSS classes**: Keep your HTML and JavaScript code separated. Use CSS classes for styling, and manipulate classes with JavaScript instead of inline styles.

Example:

```javascript
<!-- Bad: Inline style -->
<button style="background-color: #007bff; color: #fff;">Click Me</button>

<!-- Good: CSS class -->
<button class="primary-btn">Click Me</button>
```

**8.Optimize DOM manipulation**: Minimize direct DOM manipulation and use efficient approaches like template literals or libraries/frameworks that efficiently update the DOM.

Example (using template literals):

```javascript
const data = ['Item 1', 'Item 2', 'Item 3'];

function renderList(data) {
  const list = document.getElementById('list');
  list.innerHTML = '';

  data.forEach(item => {
    const listItem = document.createElement('li');
    listItem.textContent = item;
    list.appendChild(listItem);
  });
}

renderList(data);
```

**9.Use event delegation**: Attach event listeners to parent elements and utilize event delegation for handling events on dynamically added elements.

Example:

```javascript
<ul id="list">
  <!-- List items will be added dynamically -->
</ul>
```

```javascript
document.getElementById('list').addEventListener('click', event => {
  if (event.target.nodeName === 'LI') {
    // Handle click on list item
    console.log(event.target.textContent);
  }
});
```

**10.Optimize asset loading**: Minimize the number of HTTP requests and use techniques like bundling and minification to optimize asset loading.

**11.Error Handling**: Always handle errors gracefully to avoid unexpected application crashes and improve user experience.

Example:

```javascript
function divide(a, b) {
  if (b === 0) {
    throw new Error('Division by zero is not allowed.');
  }
  return a / b;
}

try {
  const result = divide(10, 0);
  console.log(result);
} catch (error) {
  console.error('An error occurred:', error.message);
}
```

**12.Use Promises or Async/Await for Asynchronous Operations**: Avoid using nested callbacks for asynchronous operations and use Promises or Async/Await to improve code readability and maintainability.

Example using Promises:

```javascript
function fetchData() {
  return fetch('https://api.example.com/data')
    .then(response => response.json());
}

fetchData()
  .then(data => console.log(data))
  .catch(error => console.error('Error fetching data:', error));
```

Example using Async/Await:

```javascript
async function fetchData() {
  try {
    const response = await fetch('https://api.example.com/data');
    const data = await response.json();
    return data;
  } catch (error) {
    throw new Error('Error fetching data:', error);
  }
}

(async () => {
  try {
    const data = await fetchData();
    console.log(data);
  } catch (error) {
    console.error(error.message);
  }
})();
```

**13.Avoid Manipulating the DOM Directly in Loops**: When performing DOM manipulation inside loops, batch the changes or use DocumentFragment to minimize layout thrashing and improve performance.

Example:

```javascript
// Bad: Directly manipulating DOM in a loop
const list = document.getElementById('list');
for (let i = 0; i < 1000; i++) {
  const listItem = document.createElement('li');
  listItem.textContent = `Item ${i}`;
  list.appendChild(listItem);
}

// Good: Batch changes using DocumentFragment
const list = document.getElementById('list');
const fragment = document.createDocumentFragment();
for (let i = 0; i < 1000; i++) {
  const listItem = document.createElement('li');
  listItem.textContent = `Item ${i}`;
  fragment.appendChild(listItem);
}
list.appendChild(fragment);
```

**14.Use Debouncing or Throttling for Event Handlers**: When handling events that could trigger frequently (e.g., resize or scroll), use debouncing or throttling techniques to reduce the number of function calls and improve performance.

Example using Lodash's `debounce` function:

```javascript
import { debounce } from 'lodash';

function handleResize() {
  // Code to handle window resize
}

window.addEventListener('resize', debounce(handleResize, 200));
```

**15.Use Semantic HTML**: Write meaningful and semantic HTML to improve accessibility, SEO, and maintainability.

Example:

```javascript
<!-- Bad: Using generic divs -->
<div class="header">
  <div class="title">My Website</div>
</div>

<!-- Good: Using semantic HTML -->
<header>
  <h1>My Website</h1>
</header>
```

**16.Use ES6 Modules instead of Global Scripts**: Organize your JavaScript code into separate modules, and use ES6 `import` and `export` statements instead of loading multiple scripts in the global scope.

Example (Module 1):

```javascript
// module1.js
export function foo() {
  // ...
}
```

Example (Module 2):

```javascript
// module2.js
export function bar() {
  // ...
}
```

Example (Main Script):

```javascript
// main.js
import { foo } from './module1.js';
import { bar } from './module2.js';

foo();
bar();
```

**17.Avoid Nested Ternary Operators**: While ternary operators can be useful for concise expressions, nesting them can lead to code that is hard to read and understand. Instead, use regular if-else statements for complex conditions.

Example:

```javascript
// Bad: Nested ternary
const result = condition1
  ? value1
  : condition2
  ? value2
  : condition3
  ? value3
  : defaultValue;

// Good: Using if-else
let result;
if (condition1) {
  result = value1;
} else if (condition2) {
  result = value2;
} else if (condition3) {
  result = value3;
} else {
  result = defaultValue;
}
```

**18.Avoid Excessive Comments**: Comments are essential for code documentation, but avoid over-commenting self-explanatory code. Let the code speak for itself whenever possible.

Example:

```javascript
// Bad: Excessive comments
function add(a, b) {
  // This function adds two numbers and returns the result
  return a + b; // Return the sum
}

// Good: Minimal, self-explanatory comments
function add(a, b) {
  return a + b;
}
```

**19.Use Object Shorthand**: When creating object literals with properties that have the same name as the variables, use object shorthand for cleaner code.

Example:

```javascript
// Bad: Repetitive code
const firstName = 'John';
const lastName = 'Doe';

const user = {
  firstName: firstName,
  lastName: lastName,
};

// Good: Object shorthand
const firstName = 'John';
const lastName = 'Doe';

const user = {
  firstName,
  lastName,
};
```

**20.Avoid Using** `eval()`: The `eval()` function can execute arbitrary code and is generally considered unsafe and bad practice. Find alternative solutions to achieve your goals without using `eval()`.

Example (Bad - Avoid `eval()`):

```javascript
const expression = '10 + 20';
const result = eval(expression);
console.log(result); // Output: 30
```

**21.Use** `textContent` Instead of `innerHTML`: When working with plain text content, prefer `textContent` over `innerHTML` to prevent potential security vulnerabilities (e.g., cross-site scripting - XSS).

Example:

```javascript
// Bad: Using innerHTML for plain text
const text = '<script>alert("Hello XSS!");</script>';
const element = document.getElementById('myElement');
element.innerHTML = text; // This will execute the script

// Good: Using textContent
const text = '<script>alert("Hello XSS!");</script>';
const element = document.getElementById('myElement');
element.textContent = text; // Treats it as plain text, no script execution
```

**22.Use** `addEventListener` Instead of Inline Event Handlers: Instead of using inline event handlers in HTML (e.g., `onclick="myFunction()"`), use `addEventListener` in JavaScript for better separation of concerns.

Example (Bad - Inline Event Handler):

```javascript
<button onclick="handleClick()">Click Me</button>
```

```javascript
function handleClick() {
  // Event handling logic
}
```

Example (Good - `addEventListener`):

```javascript
<button id="myButton">Click Me</button>
```

```javascript
document.getElementById('myButton').addEventListener('click', handleClick);

function handleClick() {
  // Event handling logic
}
```

**23.Use** `const` and `let` instead of `var`: Prefer `const` and `let` over `var` for variable declarations to avoid hoisting and block-scoping issues.

Example:

```javascript
// Bad: Using var
var x = 10;

// Good: Using const or let
const x = 10;
let y = 20;
```

**24.Use** `map()`, `filter()`, and `reduce()` for Array Operations: Utilize higher-order array methods like `map()`, `filter()`, and `reduce()` to perform operations on arrays in a functional and declarative manner.

Example using `map()`:

```javascript
const numbers = [1, 2, 3, 4, 5];
const doubledNumbers = numbers.map(num => num * 2);
console.log(doubledNumbers); // Output: [2, 4, 6, 8, 10]
```

Example using `filter()`:

```javascript
const numbers = [1, 2, 3, 4, 5];
const evenNumbers = numbers.filter(num => num % 2 === 0);
console.log(evenNumbers); // Output: [2, 4]
```

Example using `reduce()`:

```javascript
const numbers = [1, 2, 3, 4, 5];
const sum = numbers.reduce((acc, num) => acc + num, 0);
console.log(sum); // Output: 15
```

**25.Avoid** `document.write()`: The use of `document.write()` can cause unexpected behavior and overwrite the entire document if used after the page has finished loading. Use DOM manipulation methods instead.

Example (Bad - Avoid `document.write()`):

```javascript
document.write('<h1>Hello World</h1>');
```

**26.Use** `classList` for Managing CSS Classes: Instead of directly manipulating the `className`, use `classList` methods like `add()`, `remove()`, `toggle()`, and `contains()` to manage CSS classes.

Example:

```javascript
<div id="myDiv" class="container">Content</div>
```

```javascript
const element = document.getElementById('myDiv');

// Adding a class
element.classList.add('highlight');

// Removing a class
element.classList.remove('container');

// Checking if a class exists
if (element.classList.contains('highlight')) {
  // Do something
}

// Toggling a class
element.classList.toggle('active');
```

**27.Use** `requestAnimationFrame()` for Smooth Animations: When creating animations, use `requestAnimationFrame()` to ensure smooth and efficient animations that run at the optimal frame rate.

Example:

```javascript
function animate() {
  // Code to update the animation

  requestAnimationFrame(animate);
}

// Start the animation
animate();
```

**28.Avoid Synchronous AJAX Requests**: Avoid using synchronous XMLHttpRequest (XHR) as it can block the main thread, causing a poor user experience. Instead, use asynchronous requests with Promises, `async/await`, or callbacks.

Example using Promises:

```javascript
function fetchData() {
  return fetch('https://api.example.com/data')
    .then(response => response.json());
}

fetchData()
  .then(data => console.log(data))
  .catch(error => console.error('Error fetching data:', error));
```

Example using `async/await`:

```javascript
async function fetchData() {
  try {
    const response = await fetch('https://api.example.com/data');
    const data = await response.json();
    return data;
  } catch (error) {
    throw new Error('Error fetching data:', error);
  }
}

(async () => {
  try {
    const data = await fetchData();
    console.log(data);
  } catch (error) {
    console.error(error.message);
  }
})();
```

Thanks for reading :)

## Popular articles

1. [15 Advanced TypeScript Tips for Development](https://lakshmananarumugam.com/15-advanced-typescript-tips-for-development)
    
2. [Enum in javascript 🤯](https://lakshmananarumugam.com/enum-in-javascript)