Skip to content
Aabha AI Academy
Skip to reading

JavaScript · Module 8

Organize modules and debug with evidence

Split by responsibility, not by line count

A single file is helpful at first. Once it contains data rules, page rendering and storage behavior, it becomes harder to find the part you want. A module is a JavaScript file with its own scope that can explicitly export values for another module to import. Our core rules can then be tested without opening a page, while the UI code can focus on DOM behavior.

// labels.js
export function seatLabel(remaining) {
  if (remaining < 0) return "Check the event data";
  if (remaining === 0) return "Full";
  return `${remaining} places available`;
}
// app.js
import { seatLabel } from "./labels.js";
console.log(seatLabel(7));

The names in a named import must match the exported names. The path is relative to the importing file, not to whichever folder you happen to have open in the editor. Include ./ and the .js extension in our browser examples. The HTML entry point uses <script type="module" src="app.js"></script>. A module script without async waits for document parsing; you do not need to add defer to it.

What modules do not do

An export does not publish your function onto every page or make it a server API. It makes the value available to importing modules in that environment. Top-level module names do not automatically become properties on window, so typing a module-local name into the Console may not find it. Use breakpoints inside the module or temporary logging when investigating its local variables.

Modules use strict mode. Among other checks, assigning to an undeclared name is an error rather than silently creating a global. This helps reveal spelling mistakes. Local HTTP serving is important: opening module files through file:// can trigger browser security restrictions. Fix the serving setup rather than turning those restrictions off. Run version 08 — download the course ZIP (Extract it and follow the included setup instructions for examples/08/index.html.) and inspect both its app.js and labels.js.

Three different kinds of failure

A syntax error means the browser cannot parse the program, such as a missing closing brace. A runtime error happens while validly parsed code runs, such as reading a property of null. A logic error produces an answer that violates the requirement while the program runs without throwing. Treat them differently. A syntax error needs a punctuation or grammar fix; a null selector needs a DOM/path/timing investigation; an incorrect capacity label needs a rule or data correction.

Use this repeatable investigation: state expected versus observed behavior; reproduce the smallest case; inspect the first relevant error and its stack; pause at the line where the wrong value first appears; change one cause; rerun the case and a neighboring case. A stack trace lists the chain of calls leading to the error. Start near your own code, not at an unfamiliar library frame.

Pause instead of guessing

In Developer Tools, open Sources or Debugger, locate app.js, and click a line number inside the function. Trigger the relevant action. When paused, inspect local values, step over the next instruction and compare with your paper trace. Remove the breakpoint afterward. Do not leave an unexplained debugger statement in submitted work; it can pause other people's sessions.

Suppose a callback reads event.category but gets undefined. Check whether event is a DOM event object or your event-data record. Both might be called event, but they are different things. Rename them to submitEvent and eventRecord when they meet in one function. Good names reduce whole categories of confusion.

Write a small executable check

A test is another program that compares observed behavior with an expected result. Start with a pure function:

console.assert(seatLabel(0) === "Full", "Zero places should be full");
console.assert(seatLabel(7) === "7 places available", "Positive count label");

A passing assertion is usually silent; an assertion failure reports a problem. It does not necessarily stop execution or return a failing process exit code. Our supplied automated test harness uses explicit assertions and a nonzero exit for failed tests. The difference matters if a machine must decide whether all checks passed.

Choose meaningful cases, not merely many cases: normal positive count, zero boundary, negative invalid input, missing record and empty collection. A test can only check expectations you have written down. Passing tests do not prove every browser, screen reader or unexpected input works.

Before the program gets asynchronous

Be comfortable following one call from app.js into a module and back. Explain why a missing import file can prevent an entire entry module from executing. Use the Network panel to distinguish a 404 from a JavaScript exception. The next lesson adds waiting for data, so these habits will help separate “not loaded yet” from “loaded incorrectly.”

Reference: JavaScript modules.

Practice and next step

Open exercise 08. Attempt the prediction before running code. Record the observed result and explain any mismatch. The explained solution is separate so you can choose when to look.

Read the separate answers and explanations

Reading progress

10 lessons remain open to guests. Marking a lesson read records reading only; it does not award assessment credit or a certificate.

Device reading marks require browser storage. Reading is always available.

Sign in or create an account to save separate account progress. Your current page is kept.