← All posts
6 min read

JavaScript in the Browser: Programmable Web Behavior

#technology#computer-science#javascript#web
📑 On this page

HTML describes page structure and CSS controls presentation. JavaScript lets the page calculate, respond, update, and communicate without navigating for every action.

Browser JavaScript is program code executed in a controlled web environment with APIs for documents, events, networking, storage, media, and other capabilities.

The browser limits that code according to origin, permission, and sandbox rules.

Loading scripts

HTML can reference JavaScript:

<script src="/app.js" defer></script>

Important loading modes include:

  • Normal script: can block HTML parsing
  • defer: downloads in parallel and runs after parsing, preserving order
  • async: runs when ready without preserving document order
  • Module: supports imports and deferred behavior

Choosing incorrectly can delay rendering or create dependency races.

Modern applications split code into modules and load only what routes or features need.

Values and logic

JavaScript supports:

  • Numbers
  • Strings
  • Booleans
  • Objects
  • Arrays
  • Functions
  • BigInt
  • Symbols
  • null and undefined

Programs use conditions, loops, functions, and data structures like other general-purpose languages.

Dynamic typing means variables can hold values of different types. This is flexible but can produce surprising coercion.

Strict equality === avoids many implicit conversion surprises.

Events

The browser reports events:

  • Click
  • Key input
  • Pointer movement
  • Form submission
  • Network completion
  • Timer
  • Page visibility

JavaScript registers listeners:

button.addEventListener("click", () => {
  count += 1;
  output.textContent = String(count);
});

The listener runs when the event is processed.

Events propagate through capture and bubble phases, allowing a parent to handle interactions for many descendants.

DOM updates

JavaScript can read and modify the DOM:

const item = document.createElement("li");
item.textContent = "New lesson";
list.append(item);

Use text APIs for untrusted content.

Assigning untrusted strings to HTML-parsing APIs can create cross-site scripting.

Frameworks represent interface state and calculate DOM updates, but the browser ultimately renders DOM and related structures.

The event loop

Browser JavaScript commonly runs one task at a time on the main thread.

The event loop coordinates:

  • Script tasks
  • User events
  • Timers
  • Promise callbacks
  • Rendering opportunities

A long calculation blocks later input and rendering.

Breaking work into smaller tasks or moving computation to a worker preserves responsiveness.

Promises and async functions

Network and other operations complete later.

async function loadForecast() {
  const response = await fetch("/api/weather");
  if (!response.ok) throw new Error("Request failed");
  return response.json();
}

await pauses that async function, not the entire browser.

Errors need handling, and requests should support cancellation when a component or page no longer needs the result.

Race conditions can occur when an older request finishes after a newer one and overwrites current state.

A concrete shopping-cart example

When a user clicks "Add to cart":

  1. Browser dispatches a click event.
  2. JavaScript validates product state.
  3. It updates local UI optimistically or shows loading.
  4. fetch sends an HTTP request.
  5. The server validates price, stock, and identity.
  6. A response returns the authoritative cart.
  7. JavaScript updates the DOM.
  8. CSS renders the changed count and total.

The client improves interaction, but the server must never trust a price calculated only in JavaScript.

Users control their browsers and can modify requests.

Modules

ES modules allow explicit imports and exports:

import { formatPrice } from "./money.js";

Benefits include:

  • Clear dependencies
  • Reusable code
  • Scoped variables
  • Tooling and optimization

Browsers can load native modules, while build tools bundle, transform, and optimize them for deployment.

Too many tiny network modules can add overhead, but one enormous bundle delays initial interaction. Code splitting balances the trade-off.

Browser APIs

JavaScript can request capabilities through APIs:

  • Fetch
  • Geolocation
  • Clipboard
  • Camera and microphone
  • Notifications
  • Canvas
  • WebGL
  • Web Audio
  • IndexedDB

Sensitive features require permission or user activation.

Availability varies by browser, security context, and device.

Feature detection is safer than guessing from browser names.

Memory and garbage collection

JavaScript allocates objects in managed memory.

The garbage collector reclaims objects no longer reachable.

Leaks still occur when code retains references:

  • Forgotten event listeners
  • Growing caches
  • Detached DOM nodes
  • Timers
  • Global collections

Garbage collection can pause execution, so applications should avoid creating excessive temporary objects in performance-critical loops.

Developer tools provide heap snapshots and allocation profiles.

Security boundaries

JavaScript is restricted by:

  • Same-origin policy
  • CORS
  • Content Security Policy
  • Sandboxed frames
  • Permission prompts
  • Process sandboxing

It normally cannot read arbitrary local files or another site's private DOM.

Vulnerabilities such as XSS run attacker code with the page's origin authority, allowing access to data available to that page.

Escaping, sanitization, safe APIs, and strict CSP reduce risk.

Performance

Common issues include:

  • Large script downloads
  • Expensive parsing and compilation
  • Long main-thread tasks
  • Repeated layout-triggering DOM reads and writes
  • Excessive event handlers
  • Unbounded memory

Measure through browser performance tools and real-user metrics.

Removing unnecessary code often helps more than micro-optimizing a small function.

Common misunderstandings

"JavaScript is Java"

They are different languages with different histories and runtimes.

"Async functions run on another CPU thread"

They structure waiting. JavaScript continuations commonly resume on the main event loop.

"Client-side validation secures an API"

Attackers can send requests directly. The server must enforce every rule.

"Garbage collection prevents memory leaks"

It collects unreachable objects. Accidentally retained objects remain reachable and consume memory.

Knowledge check

1. What does an event listener do?

It registers code to run when the browser processes a matching event.

2. Does await block the entire browser?

No. It pauses the async function while the event loop can process other work.

3. Why should untrusted text use textContent rather than innerHTML?

Text APIs do not parse the value as executable markup, reducing injection risk.

4. What creates a JavaScript memory leak?

Code unintentionally retains references to data that is no longer needed.

The one idea to remember

JavaScript supplies programmable behavior inside a constrained browser runtime.

It reacts to events, modifies document state, requests data, and uses browser capabilities while sharing the main thread and obeying origin and permission boundaries.

Next, we will examine cookies, sessions, and local storage, the main ways web applications remember state across requests and visits.