Ad – 728Γ—90
🌱 Beginner

JavaScript Comments – Writing Clean, Documented Code

Comments are text in your source code that JavaScript completely ignores β€” they exist only for humans. Good comments make code maintainable, understandable to teammates, and easier to revisit months later. Bad comments clutter code and become misleading when they fall out of sync with the code. This lesson covers single-line, multi-line, and JSDoc comments, along with the principles that separate genuinely helpful comments from noise.

⏱️ 18 min read 🎯 Beginner πŸ“… Updated 2026

Single-Line Comments

A single-line comment starts with // and extends to the end of the line. Everything after // on that line is ignored by JavaScript.

JavaScript
// This is a standalone comment explaining the next line
const TAX_RATE = 0.08;   // 8% sales tax β€” required by state law

// Calculate the final price including tax
function addTax(price) {
  return price * (1 + TAX_RATE);
}

// Single-line comments are ideal for:
// - Brief explanations
// - Annotating specific values or magic numbers
// - Quick notes during development
πŸ’‘
Comment WHY, Not WHAT

The code already shows what is happening. Comments should explain why β€” the reason for a decision, a non-obvious constraint, a business rule, or a workaround for a known issue. // increment i above i++ is useless. // start at 1 to skip the header row is valuable.

Multi-Line Comments

Multi-line comments start with /* and end with */. Everything between these delimiters is a comment, regardless of how many lines it spans.

JavaScript
/*
  This function validates a UK postcode format.
  Valid examples: "SW1A 1AA", "EC2R 8AH", "W1A 0AX"

  Note: This is a simplified regex β€” it does NOT guarantee
  the postcode actually exists in Royal Mail's database.
  Use a postcode lookup API for verified addresses.
*/
function isValidUKPostcode(postcode) {
  const regex = /^[A-Z]{1,2}[0-9][A-Z0-9]? ?[0-9][A-Z]{2}$/i;
  return regex.test(postcode.trim());
}

/* Quick inline multi-line comment */
const MAX = /* the theoretical max before overflow */ 2147483647;

Commenting Out Code for Debugging

A common technique is temporarily commenting out code to isolate bugs or test alternatives. Most editors support Ctrl + / (or Cmd + /) to toggle line comments.

JavaScript
function processOrder(order) {
  // validateOrder(order);   // Temporarily disabled while debugging
  const total = calculateTotal(order.items);

  /*
  // Old discount logic β€” keeping for reference
  if (order.coupon) {
    total = total * 0.9;
  }
  */

  // New discount logic
  if (order.coupon && isValidCoupon(order.coupon)) {
    return total * getCouponDiscount(order.coupon);
  }

  return total;
}
⚠️
Don't Leave Commented-Out Code in Production

Commented-out code clutters your codebase, confuses other developers, and often represents dead code that should be deleted. If you need to keep old logic, use version control (git) β€” you can always retrieve deleted code from git history. Remove commented-out code before committing.

Ad – 336Γ—280

JSDoc Comments

JSDoc is a standardized comment format that documents functions, parameters, return values, and types. It uses /** */ (double asterisk) and special @ tags. IDEs like VS Code read JSDoc to provide intellisense, type hints, and hover documentation.

JavaScript
/**
 * Calculates the area of a rectangle.
 *
 * @param {number} width - The width of the rectangle in pixels.
 * @param {number} height - The height of the rectangle in pixels.
 * @returns {number} The area in square pixels.
 * @throws {Error} If width or height is negative.
 *
 * @example
 * const area = rectangleArea(10, 5);
 * console.log(area); // 50
 */
function rectangleArea(width, height) {
  if (width < 0 || height < 0) {
    throw new Error("Width and height must be non-negative.");
  }
  return width * height;
}

/**
 * Represents a user in the system.
 * @typedef {Object} User
 * @property {string} id - Unique user identifier.
 * @property {string} name - Display name.
 * @property {string} email - Email address.
 * @property {boolean} isAdmin - Whether the user has admin privileges.
 */

/**
 * Fetches a user by their ID.
 * @param {string} userId - The user's unique identifier.
 * @returns {Promise<User|null>} The user object, or null if not found.
 */
async function getUserById(userId) {
  // implementation...
}
JSDoc TagPurposeExample
@paramDocuments a parameter@param {string} name - User's name
@returnsDocuments return value@returns {number} The sum
@throwsDocuments thrown errors@throws {TypeError} If invalid input
@exampleUsage example@example myFn(1, 2) // 3
@typedefDefines a custom type@typedef {Object} Config
@deprecatedMarks outdated API@deprecated Use newFn() instead
@seeLinks to related docs@see https://mdn.io/...

Good vs Bad Comments

JavaScript
// ❌ BAD COMMENTS β€” These explain WHAT the code does (already obvious)
// Declare a variable called count and set it to 0
let count = 0;

// Add 1 to count
count++;

// Return the user's name
return user.name;

// βœ… GOOD COMMENTS β€” These explain WHY (not obvious from code)
// Start counting from 0; the display will add 1 for 1-based numbering
let count = 0;

// Increment on each failed attempt; lockout triggers at MAX_ATTEMPTS
count++;

// Return the display name β€” falls back to email prefix if name isn't set
return user.name || user.email.split("@")[0];

// βœ… GOOD: Explain a non-obvious business rule
// Per GDPR Article 17, we must not log the user's IP address
const requestLog = { timestamp, endpoint };  // IP deliberately excluded

// βœ… GOOD: Explain a workaround
// Array.from() instead of spread operator due to IE11 transpilation bug (see #GH-412)
const items = Array.from(nodeList);

TODO and FIXME Comments

It's a universal convention to use TODO: and FIXME: prefixes in comments to mark work that needs to be done. Many IDEs and linters can find and list these automatically.

JavaScript
// TODO: Add input validation before this goes to production
function saveUser(data) {
  db.insert(data);
}

// FIXME: This breaks when the user list is empty β€” returns undefined
function getFirstUser(users) {
  return users[0].name;
}

// HACK: Temporary fix for the timezone offset bug β€” remove after Q3 backend update
const adjustedDate = new Date(timestamp - 3600000);

// NOTE: This algorithm is O(nΒ²) β€” acceptable for now with small datasets,
//       but needs to be replaced with a hash map approach for scale
function findDuplicate(arr) {
  for (let i = 0; i < arr.length; i++) {
    for (let j = i + 1; j < arr.length; j++) {
      if (arr[i] === arr[j]) return arr[i];
    }
  }
}

ESLint Disable Comments

When ESLint flags a rule violation you intentionally need to break, you can disable the rule for a specific line. This is an escape hatch β€” use it sparingly and always explain why.

JavaScript
// Disable a rule for one line (add explanation!)
const result = eval(expression); // eslint-disable-line no-eval -- sandboxed input, validated upstream

// Disable for the next line
// eslint-disable-next-line no-console
console.log("Debug output:", data);

// Disable for a block
/* eslint-disable no-magic-numbers */
const RETRIES = 3;
const TIMEOUT = 5000;
const MAX_SIZE = 1048576;
/* eslint-enable no-magic-numbers */

// Disable for the entire file (rarely justified β€” use at the top)
/* eslint-disable no-unused-vars */
ℹ️
Comments and Code Organization

Use comments to group related code blocks in a file: // === UTILITY FUNCTIONS ===, // === API CALLS ===, // === EVENT HANDLERS ===. In larger codebases these sections should be split into separate files/modules, but section headers help readability in smaller files.

πŸ‹οΈ Practical Exercise

  1. Write a function calculateShipping(weight, distance) with a full JSDoc comment including @param, @returns, @example, and a description of the pricing formula.
  2. Review a function you've written in a previous exercise and identify any comments that explain what the code does. Rewrite them to explain why instead.
  3. Add a TODO: comment to a function that needs input validation, describing exactly what needs to be added.
  4. Deliberately trigger an ESLint warning (if ESLint is set up), then use an inline disable comment with an explanation.
  5. Write a multi-line /* */ comment explaining a complex algorithm or business rule in a function of your choice.

πŸ”₯ Challenge Exercise

Take the following undocumented utility file and add proper JSDoc comments to every function. Include parameter types, return types, a brief description, and at least one @example per function. Also identify which comments already present are "bad" (explain what) and which are "good" (explain why):

function clamp(value, min, max) {
  return Math.min(Math.max(value, min), max);
}
function debounce(fn, delay) {
  let timer;
  return function(...args) {
    clearTimeout(timer);
    timer = setTimeout(() => fn.apply(this, args), delay);
  };
}
function groupBy(arr, key) {
  return arr.reduce((acc, item) => {
    (acc[item[key]] = acc[item[key]] || []).push(item);
    return acc;
  }, {});
}

πŸ“‹ Summary

  • Single-line comments use //; multi-line use /* */.
  • JSDoc comments use /** */ with @param, @returns, @throws, @example tags for documenting functions.
  • Comment WHY, not WHAT β€” the code shows what happens; comments explain the reasoning.
  • Use TODO:, FIXME:, HACK:, NOTE: prefixes for actionable comments.
  • Don't commit commented-out code β€” use git history instead.
  • ESLint disable comments are a last resort; always include an explanation of why.

Interview Questions

  • What is the difference between single-line and multi-line comments in JavaScript?
  • What is JSDoc and why is it useful?
  • What makes a comment "good" vs "bad"?
  • When would you use a TODO comment vs just fixing the problem?
  • What is the @param JSDoc tag used for?

Frequently Asked Questions

Do comments affect JavaScript performance? +

In modern JavaScript, comments have effectively zero runtime performance impact. Build tools (like Webpack, Vite, or esbuild) automatically strip comments from production bundles. The only minor concern is file download size in unbuilt code, but minifiers handle this. Write as many comments as help maintainability β€” don't skip them for performance reasons.

Should I write JSDoc for every function? +

Not necessarily. Simple, self-explanatory functions with clear names and descriptive parameter names often don't need JSDoc: function double(n) { return n * 2; } is clear enough. JSDoc adds the most value for: public APIs, complex algorithms, functions with non-obvious parameter expectations, functions that throw, and any code others will need to use without reading the implementation.

What is TypeScript and how does it relate to JSDoc? +

TypeScript is JavaScript with static type syntax built in. JSDoc's type annotations ({string}, {number}, {Promise<User>}) serve a similar purpose but through comments rather than syntax. VS Code actually uses JSDoc type comments to provide TypeScript-like type checking in plain JavaScript files when you add // @ts-check at the top. Many teams use JSDoc as a lighter alternative to TypeScript.

Can I nest multi-line comments? +

No. JavaScript doesn't support nested block comments. /* outer /* inner */ still outer */ β€” the comment ends at the first */, so still outer */ becomes invalid code. If you need to comment out a block that already contains multi-line comments, convert them to single-line comments first, or use your editor's "comment out" feature which handles this automatically.

How do I automatically generate documentation from JSDoc comments? +

Use the JSDoc tool (npm install -g jsdoc). Running jsdoc src/ generates an HTML documentation site from your JSDoc comments. Other popular alternatives are TypeDoc (for TypeScript), ESDoc, and documentation.js. These tools create professional API documentation sites automatically from your code comments.