SECTION 1
Historical Context & Motivation
Since the earliest days of programming, developers have recognized that source code is read far more often than it is written. When you write a program, you might spend a few hours crafting a function, but your teammates — or even future-you — might read that function dozens of times over the life of a project. Code comments evolved as a way to embed human-readable explanations directly inside the source code, bridging the gap between what a machine executes and what a person needs to understand.
1958 • FORTRAN Introduces Comments
1972 • C Language and /* */ Syntax
1995 • JavaScript Is Born
2001 • Agile & Clean Code Movements
2015+ • Modern JS Tooling and JSDoc
Despite all of these advances, most beginner programmers still struggle with what to comment. They either write too many obvious comments that just restate the code, or they write none at all and leave future readers guessing. The central question this lesson addresses is: How do you write comments that genuinely help someone understand your code? The answer lies in explaining intent (why you did something) and assumptions (what conditions must be true for this code to work correctly).
SECTION 2
Core Principles of Effective Comments
Writing useful comments is a skill, not a chore. Great comments don't repeat the code — they add context that the code alone cannot convey. Think of comments as a conversation with the next person who reads your code, which might very well be yourself six months from now. The following principles form the foundation of comment-writing craft.
Explain WHY, Not WHAT
State Your Assumptions
Keep Comments Up-to-Date
Prefer Clear Code Over Comments
Use the Right Format
KEY TAKEAWAY
SECTION 3
Visual Explanation — Good vs. Bad Comments
The diagram below compares two approaches to commenting the same piece of code. On the left, you see comments that merely restate what the code does — these add visual clutter without adding understanding. On the right, the comments explain intent and assumptions, giving the reader genuine insight into the developer's reasoning.
Notice the pattern: in the good examples, the variable name maxRetries already tells you what the value represents. The comment adds why it is set to 10 specifically and where that number came from. This is the essence of intent-driven commenting: the code handles the 'what,' and the comment handles the 'why.'
SECTION 4
How Intent & Assumption Comments Work
Understanding the mechanics behind effective commenting starts with recognizing the two fundamental types of hidden knowledge in any codebase: intent and assumptions. Intent is the purpose behind a decision — the business requirement, the algorithm choice, or the design trade-off. Assumptions are the conditions that must hold true for the code to work correctly, even though they aren't enforced by the code itself.
JavaScript Comment Syntax
JavaScript provides three standard comment formats. Single-line comments use // and extend to the end of the line. They are ideal for brief notes about a single statement. Multi-line comments use /* */ and can span multiple lines, making them suitable for longer explanations at the top of a function or file. JSDoc comments use /** */ and follow a structured format with tags like @param and @returns; tools can parse them to auto-generate documentation.
The Intent–Assumption Framework
When you sit down to comment a piece of code, run through two mental questions. First: "Why did I write this particular line or block this way?" If the answer isn't obvious from the code, write an intent comment. Second: "What must be true about the data, the environment, or the caller for this to work?" If there's a hidden dependency, write an assumption comment. These two questions cover the vast majority of situations where comments genuinely help.
SECTION 5
Classifying Comment Types in JavaScript
Not all comments serve the same purpose. Professional developers generally classify comments into several categories, and understanding these categories helps you decide which to use. The table below breaks down the most common types you'll encounter in JavaScript projects, with a focus on which ones genuinely add value.
| Comment Type | Purpose | Example | Value Level |
|---|---|---|---|
| Intent | Explains why a specific approach was chosen | // Debounce to avoid flooding the API on each keystroke | ★★★ High |
| Assumption | States a condition the code depends on but doesn't enforce | // Assumes price is in USD cents, not dollars | ★★★ High |
| TODO / FIXME | Marks known issues or planned improvements | // TODO: Add input validation for negative values | ★★ Medium |
| Warning | Alerts about non-obvious consequences | // WARNING: Mutates the original array in place | ★★ Medium |
| JSDoc | Formal documentation for functions, classes, and modules | /** @param {string} name - User's display name */ | ★★★ High |
| Narration | Restates what the code already says | // increment i by 1 | ★ Low / Avoid |
Comment types ranked by the value they add to a JavaScript codebase
As you can see, intent comments and assumption comments are the most valuable because they capture knowledge that would otherwise exist only inside the original developer's head. Narration comments — the kind that say 'increment i' next to i++ — actively harm readability by adding noise without adding meaning. Your goal as a developing programmer should be to maximize high-value comments and eliminate narration.
Tip: The 6-Month Test
SECTION 6
Worked Example — Commenting a Real Function
Let's walk through a complete example. Imagine you're building a web app for a school cafeteria, and you need a function that calculates the discounted price for students who qualify for free or reduced-price lunch. We'll start with uncommented code and progressively add intent and assumption comments.
Adding Intent & Assumption Comments to a Discount Function
- 1
Step 1 — Read the Uncommented Code
Here is the raw function without any comments:function calcLunchPrice(basePrice, studentId, discountTier) { if (discountTier === 'free') return 0; if (discountTier === 'reduced') return basePrice * 0.4; if (basePrice > 5.00) return basePrice - 0.50; return basePrice; }A reader can see WHAT the function does — it returns different prices based on a discount tier. But several questions remain unanswered.Key questions: Why 0.4? Why 5.00? Why −0.50? Where does discountTier come from? - 2
Step 2 — Identify Hidden Intent
Ask: 'Why did the developer choose these specific numbers?' The 0.4 multiplier means students on 'reduced' lunch pay 40% of the base price. That isn't an arbitrary choice — it comes from the National School Lunch Program (NSLP) guidelines. The 0.50 discount for prices over $5.00 is a local cafeteria policy to encourage buying higher-priced healthy options. These are intent details that belong in comments.Intent identified: the 40% rate from NSLP guidelines, and the $0.50 incentive policy. - 3
Step 3 — Identify Hidden Assumptions
Ask: 'What must be true for this code to work correctly?' The function assumesbasePriceis a positive number in dollars (not cents). It assumesdiscountTieris one of exactly three values: 'free', 'reduced', or undefined/other. It also assumes the student's eligibility was already verified before this function was called.Assumptions identified: price in dollars, valid tier values, pre-verified eligibility. - 4
Step 4 — Write the Commented Version
Now we add comments that capture intent and assumptions:/** * Calculates the lunch price after applying discount tiers. * Assumes `basePrice` is in US dollars (not cents) and is > 0. * Assumes `discountTier` is validated upstream by verifyEligibility(). * @param {number} basePrice - Menu price before discounts * @param {string} studentId - Used for audit logging (not pricing) * @param {string} discountTier - 'free', 'reduced', or undefined * @returns {number} Final price the student pays */ function calcLunchPrice(basePrice, studentId, discountTier) { // NSLP 'free' tier: student pays nothing if (discountTier === 'free') return 0; // NSLP 'reduced' tier: student pays 40% per federal guidelines if (discountTier === 'reduced') return basePrice * 0.4; // Cafeteria incentive: $0.50 off meals over $5 to encourage // choosing the premium healthy option (Policy #12, Sept 2024) if (basePrice > 5.00) return basePrice - 0.50; return basePrice; }Every comment now explains WHY, not WHAT. The JSDoc header captures all major assumptions. - 5
Step 5 — Verify Comment Quality
Run through a final checklist. Does any comment simply restate the code? No — each one adds context about federal guidelines, local policy, or data expectations. Are assumptions called out? Yes — the JSDoc block states the unit (dollars, not cents) and where validation happens. Would a new teammate understand this function without asking you? Yes. The comments have done their job.Final result: a well-commented function that any developer can maintain with confidence.
SECTION 7
Strengths, Pitfalls, and Best Practices
Like any tool, comments can be used well or poorly. The difference between a helpful codebase and a frustrating one often comes down to comment quality. Understanding both the strengths and the common pitfalls of commenting will help you develop a balanced approach.
| Strengths | Pitfalls |
|---|---|
| Intent comments make code maintainable — future developers can modify logic without breaking hidden expectations. | Stale comments that contradict the current code are worse than no comments, because they actively mislead readers. |
| Assumption comments prevent bugs by making invisible dependencies visible before they cause failures. | Over-commenting every line creates visual noise and makes it harder to scan the actual logic. |
| JSDoc comments integrate with IDEs, enabling auto-complete tooltips and generated documentation. | Using comments to explain bad code instead of fixing it ('comment crutch') hides deeper design problems. |
| TODO/FIXME markers help teams track technical debt and planned improvements in a discoverable way. | Leaving commented-out code blocks in production clutters the file — use version control (Git) instead. |
Strengths and pitfalls of code comments in JavaScript projects
KEY TAKEAWAY
SECTION 8
Connecting to Professional Practices
The commenting skills you've learned in this lesson form the foundation for professional software communication practices that you'll encounter as you advance. In real-world teams, comments are just one part of a broader documentation ecosystem that includes code reviews, commit messages, pull request descriptions, and technical design documents. The intent-and-assumption mindset applies to all of these formats.
| This Lesson (Basics) | Professional Level |
|---|---|
| Single-line // comments for intent | ADRs (Architecture Decision Records) that formally document design choices and their trade-offs |
| Assumption comments in code | Contract-based programming with runtime assertions and TypeScript types that enforce assumptions |
| JSDoc for function documentation | Auto-generated API documentation sites using tools like Storybook, Swagger, or TypeDoc |
| TODO markers for known issues | Issue trackers (GitHub Issues, Jira) with linked commits so every change traces back to a requirement |
How basic comment practices scale into professional documentation workflows
As you move into AP Computer Science, college courses, or internships, you'll find that teams value developers who communicate clearly in code just as much as those who write clever algorithms. The two-question framework — "Why did I do this?" and "What must be true?" — will serve you well in every one of those contexts, whether you're writing a comment, a commit message, or a design document.
SECTION 9
Practice Problems
Question 1: CONCEPTUAL
// add 1 to counter above the line counter += 1; is considered a poor comment. What kind of comment would be more useful here?Show answer
// add 1 to counter is a narration comment — it simply restates what the code already says in English, adding no new information. Anyone who can read JavaScript already knows that counter += 1 increments the counter. A better comment would explain WHY the counter is being incremented, such as // Track failed login attempts for the lockout policy (max 5). This version tells the reader the purpose behind the increment and references a specific business rule, which is information they couldn't get from the code alone.Question 2: BASIC
function getShippingCost(weight) {
if (weight <= 0) return 0;
return weight * 2.5 + 3.99;
}
What intent and assumption would you document?Show answer
// Shipping rate: $2.50/lb plus $3.99 flat handling fee (per carrier contract, Jan 2025). This explains where the numbers 2.5 and 3.99 come from and why they were chosen. An assumption comment for the guard clause could be: // Assumes weight is in pounds; a weight of 0 or less means a digital-only order (no shipping). This clarifies the unit of measurement and explains the business logic behind returning 0, preventing a future developer from thinking it's a bug.Question 3: INTERMEDIATE
// check if score is more than 89
function isHonorRoll(score) {
return score > 89;
}Show answer
/**
* Determines if a student qualifies for the honor roll.
* The threshold of 90+ follows the school's grading policy
* (see Student Handbook §4.2). Assumes `score` is a
* weighted final percentage (0–100), not a raw point total.
* @param {number} score - Weighted final percentage
* @returns {boolean}
*/
function isHonorRoll(score) {
return score > 89;
}
This version explains the intent (school grading policy), states the assumption (score is a weighted percentage, not raw points), and even references where the rule comes from. The original comment 'check if score is more than 89' added nothing that the code didn't already say.Question 4: APPLIED
enemies is an empty array. Add comments that would have helped your teammate catch this bug before it shipped.
function getStrongestEnemy(enemies) {
let strongest = enemies[0];
for (let i = 1; i < enemies.length; i++) {
if (enemies[i].hp > strongest.hp) {
strongest = enemies[i];
}
}
return strongest;
}Show answer
enemies has at least one element. When the array is empty, enemies[0] is undefined, and accessing strongest.hp in the loop causes a crash. A proper set of comments would look like:
/**
* Finds the enemy with the highest HP to target first.
* Assumes `enemies` is a non-empty array of objects with
* a numeric `hp` property. Returns undefined if array is
* empty — callers should check for this.
* @param {Array<{hp: number}>} enemies
* @returns {Object|undefined}
*/
function getStrongestEnemy(enemies) {
// Guard: avoid crash on empty wave between levels
if (enemies.length === 0) return undefined;
...
Had the original developer written an assumption comment about needing a non-empty array, the bug would have been caught during code review or testing before it reached players.Question 5: CRITICAL THINKING
Show answer
x to maxRetries is always better than writing a comment explaining what x means. However, code fundamentally cannot express 'why' — for example, the cafeteria function's 40% rate comes from federal NSLP guidelines, and no amount of renaming could embed that context into the code itself. Similarly, the assumption that an array must be sorted can't be communicated through variable names alone. Comments cause harm when they're stale (contradicting code) or narrating (adding noise). They're irreplaceable when documenting business rules, external dependencies, or non-obvious trade-offs. The professional approach is to write clean code first and then add comments specifically where intent and assumptions would otherwise be invisible.SUMMARY
Lesson Summary
Summary
Effective code comments serve as a bridge between the developer's mind and the reader's understanding. The core skill is learning to explain intent — the why behind a decision, such as a business rule, an algorithm choice, or a performance trade-off — and assumptions — the invisible conditions that must hold true, like input formats, sort orders, or pre-validated data. JavaScript provides single-line comments (//) for brief inline notes, multi-line comments (/* */) for longer explanations, and JSDoc (/** */) for structured documentation that tools can parse automatically.
Remember the two-question framework: before commenting any code, ask "Why did I write it this way?" and "What must be true for this to work?" Avoid narration comments that restate the obvious, and always keep comments up-to-date when code changes. Prefer clear code first and then supplement with comments where the code alone cannot tell the full story. These habits form the foundation of professional software communication and will serve you well from your first group project through your career.