DEV Community

Cover image for Front end practice: Top 25+ Javascript code best practices for development
Lakshmanan Arumugam
Lakshmanan Arumugam

Posted on • Originally published at lakshmananarumugam.com

Front end practice: Top 25+ Javascript code best practices for development

In a previous article, 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:

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

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

getUsers();
Enter fullscreen mode Exit fullscreen mode

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

Example:

const PI = 3.14159;
let count = 0;

count = 10; // Valid
PI = 3; // Error
Enter fullscreen mode Exit fullscreen mode

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

Example:

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

function someFunction() {
  // ...
}

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

  function someFunction() {
    // ...
  }
})();
Enter fullscreen mode Exit fullscreen mode

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

Example:

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

// Arrow function
const add = (a, b) => a + b;
Enter fullscreen mode Exit fullscreen mode

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:

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

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

  // Call the function or attach it to the desired scope
  myFunction();
})();
Enter fullscreen mode Exit fullscreen mode

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

Example:

// 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}.`;
Enter fullscreen mode Exit fullscreen mode

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:

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

<!-- Good: CSS class -->
<button class="primary-btn">Click Me</button>
Enter fullscreen mode Exit fullscreen mode

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):

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);
Enter fullscreen mode Exit fullscreen mode

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

Example:

<ul id="list">
  <!-- List items will be added dynamically -->
</ul>
Enter fullscreen mode Exit fullscreen mode
document.getElementById('list').addEventListener('click', event => {
  if (event.target.nodeName === 'LI') {
    // Handle click on list item
    console.log(event.target.textContent);
  }
});
Enter fullscreen mode Exit fullscreen mode

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:

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);
}
Enter fullscreen mode Exit fullscreen mode

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:

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));
Enter fullscreen mode Exit fullscreen mode

Example using Async/Await:

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);
  }
})();
Enter fullscreen mode Exit fullscreen mode

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:

// 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);
Enter fullscreen mode Exit fullscreen mode

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:

import { debounce } from 'lodash';

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

window.addEventListener('resize', debounce(handleResize, 200));
Enter fullscreen mode Exit fullscreen mode

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

Example:

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

<!-- Good: Using semantic HTML -->
<header>
  <h1>My Website</h1>
</header>
Enter fullscreen mode Exit fullscreen mode

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):

// module1.js
export function foo() {
  // ...
}
Enter fullscreen mode Exit fullscreen mode

Example (Module 2):

// module2.js
export function bar() {
  // ...
}
Enter fullscreen mode Exit fullscreen mode

Example (Main Script):

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

foo();
bar();
Enter fullscreen mode Exit fullscreen mode

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:

// 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;
}
Enter fullscreen mode Exit fullscreen mode

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:

// 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;
}
Enter fullscreen mode Exit fullscreen mode

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:

// 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,
};
Enter fullscreen mode Exit fullscreen mode

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()):

const expression = '10 + 20';
const result = eval(expression);
console.log(result); // Output: 30
Enter fullscreen mode Exit fullscreen mode

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:

// 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
Enter fullscreen mode Exit fullscreen mode

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):

<button onclick="handleClick()">Click Me</button>
Enter fullscreen mode Exit fullscreen mode
function handleClick() {
  // Event handling logic
}
Enter fullscreen mode Exit fullscreen mode

Example (Good - addEventListener):

<button id="myButton">Click Me</button>
Enter fullscreen mode Exit fullscreen mode
document.getElementById('myButton').addEventListener('click', handleClick);

function handleClick() {
  // Event handling logic
}
Enter fullscreen mode Exit fullscreen mode

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:

// Bad: Using var
var x = 10;

// Good: Using const or let
const x = 10;
let y = 20;
Enter fullscreen mode Exit fullscreen mode

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():

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

Example using filter():

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

Example using reduce():

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

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()):

document.write('<h1>Hello World</h1>');
Enter fullscreen mode Exit fullscreen mode

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:

<div id="myDiv" class="container">Content</div>
Enter fullscreen mode Exit fullscreen mode
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');
Enter fullscreen mode Exit fullscreen mode

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:

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

  requestAnimationFrame(animate);
}

// Start the animation
animate();
Enter fullscreen mode Exit fullscreen mode

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:

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));
Enter fullscreen mode Exit fullscreen mode

Example using async/await:

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);
  }
})();
Enter fullscreen mode Exit fullscreen mode

Thanks for reading :)

Popular articles

  1. 15 Advanced TypeScript Tips for Development

  2. Enum in javascript 🤯

Top comments (7)

Collapse
 
dannyengelman profile image
Danny Engelman

29. Have fun programming

And together with your team decide which rules the team is going to play with

Collapse
 
ferhatavdic profile image
FerhatAvdic

When you have a deadline things get more stressful as you need to think and decide much quicker. You gotta find the solution under the pressure of time. You end up in sweat at the end of the day because of how exhaustive it can be. Its not always fun, but it sure is rewarding to know that you lived up to the challenge.

Collapse
 
rogemateos profile image
Roge

Nice Article

Collapse
 
rudacomolaplanta profile image
Andrés Ruda

It's a really good list to keep the code clean and optimal. Sure I'll follow some of your recommendations. Thanks a lot!

Collapse
 
ianbonaparte profile image
Ian Bonaparte

Great post - there were some things in here that I am definitely guilty of breaking rules on in my own career. I bookmarked this to come back to later so I can dive deeper into the why's and why nots.

Collapse
 
jeffchavez_dev profile image
Jeff Chavez

Wow. I am saving this as reference for my current projects

Collapse
 
martinfjant profile image
Martin Falk Johansson

Let and const are mentioned twice?