Skip to content

Latest commit

 

History

History
205 lines (155 loc) · 7.9 KB

REFERENCE.md

File metadata and controls

205 lines (155 loc) · 7.9 KB

JavaScript field reference

Use this alongside the 81 lessons. The lesson examples show each idea in runnable code; this page collects the most important patterns.

Language and browser

ECMAScript defines the core language: values, functions, objects, modules, promises, and more. The browser adds APIs such as document, fetch, storage, and events. Node.js provides a different host environment. A function that uses document cannot run unchanged in Node.

Bindings and values

const title = "Practice";
let attempts = 0;
attempts += 1;

const settings = { theme: "light" };
settings.theme = "dark";

Use const for a binding that will not be reassigned. The object assigned to a const binding can still change. Common primitives are string, number, boolean, bigint, symbol, null, and undefined. Arrays and functions are objects.

Equality and fallbacks

"0" === 0;          // false
0 ?? 10;            // 0
0 || 10;            // 10
Boolean([]);        // true

Prefer strict equality. Use nullish coalescing when zero, false, or an empty string should remain valid.

Functions and data

function total(items) {
  return items
    .filter((item) => item.valid)
    .reduce((sum, item) => sum + item.amount, 0);
}

const original = { title: "Read", done: false };
const updated = { ...original, done: true };

Keep calculations separate from the DOM when possible. map transforms, filter selects, find returns the first match, and reduce accumulates. Spread creates a shallow copy; nested objects may still be shared.

DOM updates

const item = document.createElement("li");
item.textContent = userInput;
document.querySelector("#list").append(item);

Use textContent for user-provided text. Avoid interpreting unknown text as HTML. Check that a selector matched before using the result.

Events and forms

const form = document.querySelector("form");
form.addEventListener("submit", (event) => {
  event.preventDefault();
  const data = new FormData(form);
  const query = String(data.get("query") ?? "").trim();
  // Validate, update state, then render.
});

Listen for form submission, not only a button click, so Enter-key submission works. Delegated listeners can handle buttons added to a list later. Keep accessible names and focus behavior in sync with visual state.

Promises and async functions

async function loadItems(signal) {
  const response = await fetch("./items.json", { signal });
  if (!response.ok) throw new Error("HTTP " + response.status);
  return response.json();
}

try {
  const items = await loadItems(new AbortController().signal);
  console.log(items);
} catch (error) {
  console.error(error);
}

A fetch promise can fulfill with a 404 or 500 response, so check response.ok. Show loading, empty, success, and error states separately. Use AbortController when old work should be cancelled.

Modules

// math.mjs
export function add(a, b) {
  return a + b;
}

// main.js
import { add } from "./math.mjs";
console.log(add(2, 3));

Browser modules should be served from a supported origin. Use the local-server command in the course README. Keep exports small and dependencies explicit.

State and rendering

let state = { count: 0 };

function render() {
  document.querySelector("#count").textContent = String(state.count);
}

function increment() {
  state = { ...state, count: state.count + 1 };
  render();
}

State is the source of truth. Event handlers change state; render updates the page. Derive counts and filtered results from state instead of storing duplicate values that can disagree.

Testing and debugging

  1. Reproduce the issue and read the first relevant error.
  2. Inspect actual values with a breakpoint or a small log.
  3. Test a pure function with normal, boundary, and invalid inputs.
  4. Check the page with keyboard, narrow width, and a slow or failed request.
  5. Fix one cause at a time and retest the original scenario.

The Node test runner can run dependency-free tests with node --test.

Security and performance

  • Treat external and user-entered text as data; insert it with textContent.
  • Validate destinations before building links from outside data.
  • Never store secrets in localStorage.
  • Measure expensive work before optimizing.
  • Keep the main thread responsive; use a worker for CPU-heavy work when measurement justifies it.
  • Remove timers and listeners when their owning UI is removed.

Authoritative references

Advanced language and browser APIs

const privateData = new WeakMap();
const metadata = Symbol("metadata");

function observe(target) {
  return new Proxy(target, {
    set(object, key, value, receiver) {
      console.debug("update", String(key));
      return Reflect.set(object, key, value, receiver);
    }
  });
}

Use Proxy only when intercepting object operations materially simplifies a contract; traps must respect platform invariants. WeakMap is useful for object-keyed metadata whose lifetime should follow the key.

async function readAll(stream) {
  const reader = stream.getReader();
  try {
    const chunks = [];
    while (true) {
      const { value, done } = await reader.read();
      if (done) return chunks;
      chunks.push(value);
    }
  } finally {
    reader.releaseLock();
  }
}

Streams can process large responses incrementally. Respect cancellation and backpressure instead of accumulating unbounded chunks. IndexedDB is asynchronous structured storage; group related operations into transactions. Service workers require an appropriate secure origin and have an update lifecycle. Test cache changes and scope explicitly.

Use Intl.NumberFormat, Intl.DateTimeFormat, and Intl.Segmenter instead of assuming punctuation, date order, or character boundaries. Add CSP as a defense-in-depth policy and continue to construct DOM safely. Use PerformanceObserver and browser performance tools to connect measured work to user-visible delays.

For real-time systems, handle disconnects and stale data explicitly. BroadcastChannel coordinates same-origin contexts; WebSockets require an endpoint and application-level reconnect policy. Global error reporting should avoid sensitive data and should not hide failures from users.

Advanced authoritative references