- 1. Use
const by default.
Use const when the variable reference should not be
reassigned.
const appName = "Dashboard";
- 2. Use
let only when reassignment is needed.
Use let for counters, loops, and values that change.
let count = 0;
count += 1;
- 3. Avoid
var.
var is function-scoped and can create hoisting confusion.
Prefer let and const.
let total = 100;
const tax = 8;
- 4. Use arrow functions for callbacks.
Arrow functions keep callback code shorter and cleaner.
const numbers = [1, 2, 3];
const doubled =
numbers.map((number) => number * 2);
- 5. Use regular functions for object methods.
Regular methods have their own this.
const user =
{
name: "Alice",
showName() {
return this.name;
}
};
- 6. Use template literals for readable strings.
Template literals make variables inside strings easier to read.
const name = "John";
const message =
`Welcome, ${name}!`;
- 7. Use destructuring for objects.
Destructuring reduces repeated property access.
const user =
{
name: "Alice",
role: "Admin"
};
const { name, role } =
user;
- 8. Use destructuring for arrays.
Array destructuring makes position-based values cleaner.
const colors =
["red", "green", "blue"];
const [firstColor, secondColor] =
colors;
- 9. Use default parameters.
Default parameters avoid manual fallback checks.
function greet(name = "Guest") {
return `Hello ${name}`;
}
- 10. Use rest parameters instead of
arguments.
Rest parameters are clearer and work well with arrow functions.
function sum(...numbers) {
return numbers.reduce(
(total, number) => total + number,
0
);
}
- 11. Use spread syntax to copy arrays.
Spread creates a shallow copy without mutating the original array.
const items = ["A", "B"];
const copy =
[...items];
- 12. Use spread syntax to merge arrays.
Spread makes array merging readable.
const frontend =
["HTML", "CSS"];
const advanced =
["JavaScript", "React"];
const skills =
[...frontend, ...advanced];
- 13. Use spread syntax to copy objects.
Object spread is useful for immutable updates.
const user =
{
name: "Alice",
active: true
};
const updatedUser =
{
...user,
active: false
};
- 14. Use enhanced object property shorthand.
When key and variable names match, use shorthand.
const name = "Alice";
const role = "Admin";
const user =
{
name,
role
};
- 15. Use concise object methods.
ES6 method syntax is cleaner than assigning function expressions.
const calculator =
{
add(a, b) {
return a + b;
}
};
- 16. Use computed property names when needed.
Computed properties help build dynamic object keys.
const field = "email";
const formData =
{
[field]: "user@example.com"
};
- 17. Use
map() for transformations.
Use map() when every item should become a new value.
const prices =
[10, 20, 30];
const withTax =
prices.map((price) => price * 1.08);
- 18. Use
filter() for selecting items.
Use filter() when only matching items should remain.
const users =
[
{ name: "Alice", active: true },
{ name: "Bob", active: false }
];
const activeUsers =
users.filter((user) => user.active);
- 19. Use
reduce() for totals and summaries.
reduce() is useful when an array becomes one result.
const total =
[10, 20, 30].reduce(
(sum, value) => sum + value,
0
);
- 20. Use
find() for one matching item.
Use find() instead of filter() when you need
only one result.
const product =
products.find(
(item) => item.id === 101
);
- 21. Use
some() for at-least-one checks.
some() returns true when at least one item matches.
const hasError =
fields.some((field) => field.error);
- 22. Use
every() for all-items checks.
every() returns true only when all items pass.
const isFormValid =
fields.every((field) => field.valid);
- 23. Use
includes() for simple value checks.
includes() is cleaner than checking index positions.
const roles =
["admin", "editor"];
const canEdit =
roles.includes("editor");
- 24. Avoid mutation when updating arrays.
Prefer creating new arrays for predictable state updates.
const updatedItems =
items.map((item) => {
if (item.id === 1) {
return {
...item,
selected: true
};
}
return item;
});
- 25. Avoid mutation when removing array items.
Use filter() instead of directly changing the array.
const remainingUsers =
users.filter(
(user) => user.id !== removedUserId
);
- 26. Use modules for reusable code.
Export reusable functions and import them where needed.
export function formatPrice(price) {
return "$" + price.toFixed(2);
}
- 27. Use named exports for multiple utilities.
Named exports make imports clear and tree-shakeable.
export const appVersion = "1.0.0";
export function logMessage(message) {
console.log(message);
}
- 28. Use default exports for one main value.
Default exports are useful when a file has one primary purpose.
export default function Button() {
return "Button";
}
- 29. Use classes only when they improve structure.
Classes are useful for models, services, and reusable behavior.
class UserService {
constructor(apiUrl) {
this.apiUrl = apiUrl;
}
getUsers() {
return fetch(this.apiUrl);
}
}
- 30. Prefer composition over large inheritance chains.
Keep behavior small and reusable instead of deeply nested classes.
const canLog =
{
log(message) {
console.log(message);
}
};
- 31. Use Promises for async operations.
Promises make async success and failure easier to handle.
fetch("/api/users")
.then((response) => response.json())
.then((users) => console.log(users))
.catch((error) => console.error(error));
- 32. Use async await for readable async code.
Async await is easier to read for multi-step async flows.
async function loadUsers() {
const response =
await fetch("/api/users");
return response.json();
}
- 33. Always handle async errors.
Use try catch around awaited operations.
async function loadData() {
try {
const response =
await fetch("/api/data");
return await response.json();
} catch (error) {
console.error(error.message);
return null;
}
}
- 34. Use
Promise.all() for parallel requests.
Use it when requests do not depend on each other.
const [users, products] =
await Promise.all(
[
fetch("/api/users").then((res) => res.json()),
fetch("/api/products").then((res) => res.json())
]
);
- 35. Use
Promise.allSettled() for optional tasks.
It lets some tasks fail without stopping all results.
const results =
await Promise.allSettled(
[
fetch("/api/news"),
fetch("/api/weather")
]
);
- 36. Avoid async work inside
forEach().
forEach() does not wait for async callbacks.
for (const id of ids) {
await loadUser(id);
}
- 37. Use
for...of for sequential async tasks.
Use it when each async step must finish before the next one starts.
for (const file of files) {
await uploadFile(file);
}
- 38. Use
for await...of for async iterables.
This is useful for streams and async generators.
for await (const chunk of stream) {
console.log(chunk);
}
- 39. Use optional chaining for safe property access.
Optional chaining avoids errors when values are missing.
const city =
user?.address?.city;
- 40. Use nullish coalescing for safe defaults.
Use ?? when only null or
undefined should use the fallback.
const pageSize =
settings.pageSize ?? 20;
- 41. Prefer strict equality.
Use === and !== to avoid type conversion
surprises.
if (status === "active") {
showDashboard();
}
- 42. Use meaningful variable names.
Clear names reduce comments and improve maintainability.
const activeUsers =
users.filter((user) => user.active);
- 43. Keep functions small and focused.
A function should do one clear task.
function calculateTax(price, rate) {
return price * rate;
}
- 44. Avoid deeply nested code.
Return early to make conditions easier to read.
function saveUser(user) {
if (!user) {
return null;
}
return api.save(user);
}
- 45. Use object parameters for many arguments.
Object parameters make function calls easier to understand.
function createUser(options) {
const { name, email, role } =
options;
return {
name,
email,
role
};
}
- 46. Use Set for unique values.
Set removes duplicate values easily.
const tags =
["js", "css", "js"];
const uniqueTags =
[...new Set(tags)];
- 47. Use Map for key-value collections.
Map is useful when keys are dynamic or not simple strings.
const cache =
new Map();
cache.set("users", []);
const users =
cache.get("users");
- 48. Avoid mixing data transformation and side effects.
Keep transformation methods pure where possible.
const names =
users.map((user) => user.name);
- 49. Use comments only when they add real value.
Prefer clear code first, comments second.
// Retry once because this API may fail during cold start
await retryOnce(loadReport);
- 50. Use linting and formatting tools.
ESLint and Prettier help keep ES6 code consistent across teams.
const userName =
formatUserName(user);