JavaScript Best Practices

Use these guidelines to write code that’s readable, reliable, and fast. Each topic includes a short example and a Try-it editor.

1) Clear Naming & Small Functions

Choose descriptive names and keep functions focused on one task.


// Bad
function doIt(a){ return a*1.18; }
// Good
function addGst(amount){ return amount*1.18; }

2) Prefer const, then let; avoid var

const prevents accidental reassignments; let when the value must change. var is function-scoped and risky.


const TAX = 0.18;
let total = 0;
total += 100 * (1+TAX);

3) Use Strict Equality (===/!==)

Avoid type-coercion surprises by using strict comparisons.


// "5" == 5 is true (coercion). Prefer strict:
console.log('5' === 5); // false

4) Null-Safety: ?. and ??

Safely access deep paths and provide defaults only for null/undefined.


const user = { profile: { name: 'Sonu' } };
const nick = user.profile?.nick ?? 'Guest';

5) Prefer Pure Functions & Guard Clauses

Pure functions are easier to test. Guard clauses reduce nested ifs.


// Guard clause
function discount(price, percent) {
  if(percent <= 0) return price;
  return price * (1 - percent);
}

6) Use Modern Array/Object Patterns

Prefer map/filter/reduce to manual loops; use destructuring & spread for clarity.


const prices = [100,250,60];
const withTax = prices.map(p => p*1.18);
const sum = prices.reduce((a,b) => a+b, 0);

7) Async/Await with Proper Error Handling

Wrap awaits in try...catch. For parallel tasks, use Promise.all.


async function fetchUser(id) {
  try {
    const res = await fetch(`/api/users/${id}`);
    if(!res.ok) throw new Error('HTTP '+res.status);
    return await res.json();
  } catch(e) {
    console.error(e); throw e;
  }
}

8) DOM & Performance

Minimize reflows: batch updates, use fragments, debounce frequent events.


// Debounce a resize handler
function debounce(fn, ms) {
  let t;
  return (...args) => { clearTimeout(t); t = setTimeout(() => fn(...args), ms); };
}
window.addEventListener('resize', debounce(() => console.log('resized'), 200));

9) Accessibility (A11y)

Ensure interactive controls are keyboard reachable and labeled.


<button aria-label="Open menu" id="menuBtn"></button>
<script>
  document.getElementById('menuBtn')
    .addEventListener('keydown', (e) => {
      if(e.key === 'Enter') { /* open */ }
    });
</script>

10) Security: Avoid XSS & Unsafe Eval

Never insert untrusted HTML with innerHTML. Prefer textContent. Avoid eval.


const unsafe = '<img src=x onerror="alert(1)">';
const el = document.getElementById('out');
// el.innerHTML = unsafe; // ❌ dangerous
el.textContent = unsafe; // ✅ safe text output
Also: Validate inputs, sanitize server responses, use Content Security Policy (CSP), and never expose secrets in front-end code.

11) Organize with Modules

Split code by feature. Keep one responsibility per file and use a barrel file to re-export.


// api/users.js
export async function getUser(id){ /* ... */ }

// api/index.js
export * from './users.js';

12) Testing, Linting & Formatting

Add quick assertions; use a linter/formatter to keep code consistent.


// Tiny assertion helper
function assert(cond, msg) {
  if(!cond) throw new Error(msg);
}
assert(2+2 === 4, 'math broke');
Tip: Use ESLint + Prettier to catch mistakes and format code automatically.

13) Debugging Tips

Use DevTools: breakpoints, debugger, network tab, performance panel.


function calc(x) {
  debugger; // opens DevTools if not already
  return x*2;
}
calc(5);
Checklist: const over let=== over ==?. and ??pure functionsmap/filter/reduceasync/await + try/catchdebounce/throttlea11y labels & keyboardno eval / innerHTMLlint & format