Skip to main content

Understanding the Browser Environment and BOM in JavaScript

Introduction

When you write JavaScript, your code does not run in a vacuum. It runs inside a host environment, a platform that provides the language with objects, functions, and APIs that go far beyond what the core JavaScript specification defines. The most common host environment is the web browser.

The browser gives JavaScript the ability to interact with web pages, read the URL bar, navigate through history, detect the user's device, set timers, make network requests, and much more. None of these capabilities are part of the JavaScript language itself. They are provided by the browser as the host environment.

Understanding how the browser environment is structured is foundational knowledge. Before you can manipulate a web page, handle user events, or build any interactive feature, you need to understand the three major pieces that make up the browser's JavaScript world: the window object (the global root of everything), the DOM (Document Object Model, which represents the page), and the BOM (Browser Object Model, which represents everything else the browser provides).

In this guide, you will learn how JavaScript fits into the browser, what the window object really is, how the DOM and BOM are organized, and which specifications govern each piece. This conceptual map will make every subsequent topic in browser-side JavaScript clearer and easier to learn.

The Browser as a JavaScript Host Environment

JavaScript was designed from the beginning to be an embedded language. Unlike languages like Python or Java, which have their own standard libraries for file I/O, networking, and system access, JavaScript relies on its host environment to provide these capabilities.

A host environment is any platform that embeds the JavaScript engine and provides additional objects and functions. The two most important host environments are:

  • Web browsers (Chrome, Firefox, Safari, Edge): Provide the DOM, BOM, fetch(), setTimeout(), and everything related to web pages
  • Node.js: Provides file system access, HTTP servers, child processes, and everything related to server-side development

The same JavaScript language runs in both environments, but the objects and APIs available are completely different:

// This works in BOTH browser and Node.js (core JavaScript)
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(n => n * 2);
console.log(doubled); // [2, 4, 6, 8, 10]

// This works ONLY in a browser (provided by the browser environment)
document.getElementById('app');
window.alert('Hello!');
navigator.language;

// This works ONLY in Node.js (provided by the Node.js environment)
// const fs = require('fs');
// fs.readFileSync('/etc/hosts');
// process.env.HOME;

The core language features (variables, functions, arrays, promises, classes, etc.) are defined by the ECMAScript specification. Everything else, including document, window, setTimeout, fetch, alert, and console, is provided by the host environment.

note

Even console.log() is technically not part of the JavaScript language specification. It is provided by the host environment. Both browsers and Node.js happen to provide it, but they are under no obligation to do so, and the exact behavior can differ between environments.

What the Browser Provides

When JavaScript runs in a browser, it has access to a rich set of APIs organized into a hierarchy. At the very top of this hierarchy sits one object that contains everything else: the window object.

window (global object)
├── DOM (Document Object Model)
│ └── document
│ ├── document.documentElement (<html>)
│ ├── document.head (<head>)
│ └── document.body (<body>)
│ ├── <div>, <p>, <span>, ...
│ └── text nodes, comment nodes, ...

├── BOM (Browser Object Model)
│ ├── navigator (browser/device info)
│ ├── location (current URL)
│ ├── history (navigation history)
│ ├── screen (display info)
│ ├── fetch() (network requests)
│ ├── setTimeout() / setInterval()
│ ├── alert() / confirm() / prompt()
│ └── localStorage / sessionStorage

└── JavaScript Core (ECMAScript)
├── Object, Array, Map, Set, ...
├── Promise, async/await
├── String, Number, Boolean, ...
└── Math, Date, JSON, RegExp, ...

This diagram is the map for the entire browser-side JavaScript world. Every API you use in the browser belongs to one of these three categories.

The window Object: Global Object and Browser Interface

The window object serves a dual role in the browser. It is simultaneously the JavaScript global object and the browser window interface. These two roles are merged into a single object.

Role 1: The Global Object

In any JavaScript environment, there is a "global object" that holds global variables, functions, and built-in objects. In the browser, that global object is window:

// Global variables become properties of window
var greeting = 'Hello';
console.log(window.greeting); // "Hello"

// Global functions become methods of window
function sayHi() {
return 'Hi!';
}
console.log(window.sayHi()); // "Hi!"

// Built-in objects are properties of window
console.log(window.Array); // function Array() { ... }
console.log(window.Object); // function Object() { ... }
console.log(window.Promise); // function Promise() { ... }
console.log(window.Math); // Math object
console.log(window.JSON); // JSON object

Because window is the global object, you can access its properties without the window. prefix:

// These are equivalent
window.console.log('Hello');
console.log('Hello');

// These are equivalent
window.setTimeout(() => {}, 1000);
setTimeout(() => {}, 1000);

// These are equivalent
window.document.title;
document.title;
caution

Variables declared with let and const do not become properties of window. Only var declarations and explicit window.property assignments do:

var oldVar = 'I am on window';
let newLet = 'I am NOT on window';
const newConst = 'I am NOT on window either';

console.log(window.oldVar); // "I am on window"
console.log(window.newLet); // undefined
console.log(window.newConst); // undefined

// Explicit assignment always works
window.myGlobal = 'I am on window';
console.log(window.myGlobal); // "I am on window"

This is by design. let and const were introduced partly to avoid polluting the global object with every variable declaration.

Role 2: The Browser Window Interface

Beyond being the global object, window represents the browser window (or tab) itself. It provides properties and methods for controlling the browser:

// Window dimensions
console.log(window.innerWidth); // Viewport width in pixels
console.log(window.innerHeight); // Viewport height in pixels
console.log(window.outerWidth); // Full browser window width
console.log(window.outerHeight); // Full browser window height

// Scroll position
console.log(window.scrollX); // Horizontal scroll offset
console.log(window.scrollY); // Vertical scroll offset

// Browser dialogs
window.alert('Message');
window.confirm('Are you sure?');
window.prompt('Enter your name:');

// Timers
window.setTimeout(() => console.log('Later'), 1000);
window.setInterval(() => console.log('Tick'), 1000);

// Opening and closing windows
const popup = window.open('https://example.com', '_blank', 'width=400,height=300');
window.close(); // Close the current window (with restrictions)

// Frame information
console.log(window.frames); // Collection of child frames
console.log(window.parent); // Parent window (if in a frame)
console.log(window.top); // Topmost window
console.log(window.self); // Reference to window itself (window.self === window)

globalThis: The Universal Global Object

Since different environments have different names for the global object (window in browsers, global in Node.js, self in Web Workers), ES2020 introduced globalThis as a universal reference that works everywhere:

// Works in any environment
console.log(globalThis);

// In a browser:
console.log(globalThis === window); // true

// In Node.js:
// console.log(globalThis === global); // true

// In a Web Worker:
// console.log(globalThis === self); // true

If you are writing code that might run in multiple environments, use globalThis instead of window.

DOM: The Document Object Model

The DOM (Document Object Model) is the most important part of the browser environment for web developers. It represents the HTML page as a tree of objects that JavaScript can read, modify, create, and delete.

What Is the DOM?

When the browser loads an HTML page, it does not just display the raw text. It parses the HTML and creates an in-memory tree structure where every HTML element, text fragment, and comment becomes a node (an object) in the tree. This tree is the DOM.

Consider this simple HTML:

<!DOCTYPE html>
<html>
<head>
<title>My Page</title>
</head>
<body>
<h1>Hello</h1>
<p>Welcome to my page.</p>
</body>
</html>

The browser creates this tree:

document
└── html
├── head
│ └── title
│ └── "My Page" (text node)
└── body
├── h1
│ └── "Hello" (text node)
└── p
└── "Welcome to my page." (text node)

Every box in this tree is a DOM node, which is a JavaScript object. The document object is the entry point, the root of the entire tree:

// The document object is the root of the DOM
console.log(document);

// Access the <html> element
console.log(document.documentElement);

// Access the <head> element
console.log(document.head);

// Access the <body> element
console.log(document.body);

// Access the page title
console.log(document.title); // "My Page"

// Find elements
const heading = document.querySelector('h1');
console.log(heading.textContent); // "Hello"

// Modify elements
heading.textContent = 'Hello, World!';
heading.style.color = 'blue';

// Create new elements
const newParagraph = document.createElement('p');
newParagraph.textContent = 'This was added by JavaScript.';
document.body.appendChild(newParagraph);

// Remove elements
const oldParagraph = document.querySelector('p');
oldParagraph.remove();

The DOM Is Not the HTML Source

A critical concept: the DOM is not the HTML source code. It is a live, in-memory representation that can differ from the original HTML in several ways:

  1. The browser auto-corrects invalid HTML when building the DOM. Missing <body> or <html> tags are added automatically. Improperly nested tags are fixed.

  2. JavaScript can modify the DOM after the page loads. The changes appear on screen but do not change the HTML file.

  3. The DOM includes nodes you might not expect, like text nodes for whitespace between tags.

<!-- This invalid HTML: -->
<p>One
<p>Two

<!-- Becomes this valid DOM: -->
<!-- <html><head></head><body><p>One</p><p>Two</p></body></html> -->
// JavaScript modifies the DOM, not the HTML file
document.title = 'New Title';
// The page title changes, but the .html file on the server is unchanged

What the DOM Provides

The DOM is a massive API. Here is a preview of its capabilities (each of these is covered in depth in later articles):

// Finding elements
document.getElementById('myId');
document.querySelector('.my-class');
document.querySelectorAll('div.container > p');
document.getElementsByTagName('p');

// Reading and modifying content
element.textContent; // Get/set text
element.innerHTML; // Get/set HTML
element.outerHTML; // Get/set element + its HTML

// Attributes
element.getAttribute('href');
element.setAttribute('data-id', '42');
element.classList.add('active');
element.classList.remove('hidden');

// Styles
element.style.color = 'red';
element.style.fontSize = '18px';
getComputedStyle(element).marginTop;

// Events
element.addEventListener('click', handler);
element.removeEventListener('click', handler);

// Creating and modifying the tree
document.createElement('div');
parent.appendChild(child);
parent.removeChild(child);
element.remove();
element.cloneNode(true);

// Navigation
element.parentNode;
element.childNodes;
element.firstChild;
element.nextSibling;
element.children; // Element children only
element.firstElementChild; // First element child

The DOM is covered extensively in its own dedicated module. The key takeaway here is that document is your entry point to the entire page structure, and it is a property of window.

BOM: The Browser Object Model

The BOM (Browser Object Model) encompasses everything the browser provides to JavaScript outside the DOM. While the DOM deals with the page content, the BOM deals with the browser itself: its URL bar, navigation history, screen properties, device information, and various utility functions.

Unlike the DOM, which has a formal specification (the DOM Standard), the BOM was historically a loose collection of objects with no unified specification. Most BOM features are now standardized under the HTML specification, but the term "BOM" persists as a useful way to group these browser-provided objects.

The navigator object provides information about the browser and the user's device:

// Browser identification
console.log(navigator.userAgent);
// "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36
// (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"

// Language
console.log(navigator.language); // "en-US"
console.log(navigator.languages); // ["en-US", "en", "fr"]

// Online status
console.log(navigator.onLine); // true or false

window.addEventListener('online', () => console.log('Back online!'));
window.addEventListener('offline', () => console.log('Gone offline!'));

// Platform
console.log(navigator.platform); // "MacIntel", "Win32", "Linux x86_64"

// Clipboard API
await navigator.clipboard.writeText('Copied text!');
const text = await navigator.clipboard.readText();

// Geolocation
navigator.geolocation.getCurrentPosition(
(position) => {
console.log('Latitude:', position.coords.latitude);
console.log('Longitude:', position.coords.longitude);
},
(error) => {
console.error('Geolocation error:', error.message);
}
);

// Device memory (approximate, in GB)
console.log(navigator.deviceMemory); // 8 (or 4, 2, 1, 0.5, 0.25)

// Number of CPU cores
console.log(navigator.hardwareConcurrency); // 8

// Send data when the page is about to unload
navigator.sendBeacon('/api/analytics', JSON.stringify({ event: 'page_leave' }));

// Service Worker registration
navigator.serviceWorker.register('/sw.js');

// Media devices (cameras, microphones)
const devices = await navigator.mediaDevices.enumerateDevices();
caution

Do not rely on navigator.userAgent for browser detection. The user agent string is notoriously unreliable because every browser includes other browsers' identifiers for historical compatibility reasons. Chrome's user agent contains "Safari", Edge's contains "Chrome", and so on. Use feature detection instead:

// WRONG: Browser detection via user agent
if (navigator.userAgent.includes('Chrome')) {
// This is unreliable: many browsers include "Chrome"
}

// CORRECT: Feature detection
if ('IntersectionObserver' in window) {
// Use IntersectionObserver
} else {
// Use a fallback
}

if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js');
}

location: The Current URL

The location object represents the current URL of the page. It lets you read URL components and navigate to new pages:

// Given URL: https://example.com:8080/path/page?q=search&lang=en#section2

console.log(location.href); // "https://example.com:8080/path/page?q=search&lang=en#section2"
console.log(location.protocol); // "https:"
console.log(location.host); // "example.com:8080"
console.log(location.hostname); // "example.com"
console.log(location.port); // "8080"
console.log(location.pathname); // "/path/page"
console.log(location.search); // "?q=search&lang=en"
console.log(location.hash); // "#section2"
console.log(location.origin); // "https://example.com:8080"

Navigating to a new page:

// Navigate to a new URL (adds to history)
location.href = 'https://example.com/new-page';

// Same as above
location.assign('https://example.com/new-page');

// Navigate WITHOUT adding to history (replaces current entry)
location.replace('https://example.com/new-page');
// User cannot press "Back" to return

// Reload the current page
location.reload();

Working with query parameters using the URL and URLSearchParams APIs:

// Parse query parameters from the current URL
const params = new URLSearchParams(location.search);

console.log(params.get('q')); // "search"
console.log(params.get('lang')); // "en"
console.log(params.has('page')); // false

// Modify query parameters without reloading
const url = new URL(location.href);
url.searchParams.set('page', '2');
url.searchParams.delete('lang');

// Update URL without reload (using History API)
history.pushState({}, '', url);

history: Navigation History

The history object lets you navigate through the browser's session history (the pages the user has visited in the current tab):

// Navigate back and forward
history.back(); // Same as clicking the Back button
history.forward(); // Same as clicking the Forward button
history.go(-2); // Go back 2 pages
history.go(1); // Go forward 1 page

// Number of entries in the session history
console.log(history.length);

The History API also supports modifying the URL without reloading the page, which is the foundation of client-side routing in single-page applications (SPAs):

// Add a new entry to the history stack
history.pushState(
{ page: 'about' }, // State object (accessible later)
'', // Title (mostly ignored by browsers)
'/about' // New URL to display
);
// URL bar now shows "/about" but NO page reload occurs

// Replace the current entry (no new history entry)
history.replaceState(
{ page: 'about', scrollPos: 250 },
'',
'/about'
);

// Listen for the user pressing Back/Forward
window.addEventListener('popstate', (event) => {
console.log('Navigation occurred');
console.log('State:', event.state);
// { page: 'about' } (the state object passed to pushState)

// Render the appropriate page content based on the state
if (event.state && event.state.page) {
renderPage(event.state.page);
}
});

This is how frameworks like React Router, Vue Router, and Angular Router implement client-side navigation. They use pushState to change the URL and popstate to detect when the user presses the browser's Back/Forward buttons.

screen: Display Information

The screen object provides information about the user's physical display:

// Screen dimensions (physical screen, not browser window)
console.log(screen.width); // 1920
console.log(screen.height); // 1080

// Available screen space (excludes taskbar/dock)
console.log(screen.availWidth); // 1920
console.log(screen.availHeight); // 1040 (minus taskbar)

// Color depth
console.log(screen.colorDepth); // 24 (bits)
console.log(screen.pixelDepth); // 24 (bits)

// Device pixel ratio (for high-DPI/Retina displays)
console.log(window.devicePixelRatio); // 2 on Retina, 1 on standard

screen properties are primarily useful for analytics (knowing your users' screen sizes) and for positioning popup windows. For responsive design, you should use CSS media queries and window.innerWidth/window.innerHeight instead, as they reflect the actual viewport the user sees.

Other BOM Features

The BOM includes many more APIs that do not fit neatly into the objects above:

// Timers
const timerId = setTimeout(() => console.log('Delayed'), 2000);
const intervalId = setInterval(() => console.log('Repeating'), 1000);
clearTimeout(timerId);
clearInterval(intervalId);

// Network requests
fetch('/api/data').then(r => r.json());

// Storage
localStorage.setItem('theme', 'dark');
sessionStorage.setItem('tempData', 'value');

// Dialogs
alert('Information');
const confirmed = confirm('Proceed?');
const name = prompt('Your name?');

// Animation frame
requestAnimationFrame((timestamp) => {
// Smooth animation callback
});

// Performance
console.log(performance.now()); // High-resolution timestamp
console.log(performance.timing); // Page load timing

// Encoding/Decoding
const encoded = btoa('Hello'); // Base64 encode
const decoded = atob(encoded); // Base64 decode

// Structured cloning
const deepCopy = structuredClone({ nested: { data: [1, 2, 3] } });

// Web Workers
const worker = new Worker('worker.js');

// Intersection Observer
const observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
console.log('Element is visible');
}
});
});

The DOM Standard and the HTML Specification

The browser environment is governed by several overlapping specifications. Understanding which specification defines what helps you find authoritative documentation and understand why certain APIs work the way they do.

The ECMAScript Specification

Maintained by TC39 (Technical Committee 39 of Ecma International).

Defines the core JavaScript language: variables, types, operators, functions, classes, promises, iterators, modules, and all the built-in objects like Array, Object, Map, Set, Math, Date, JSON, RegExp, Promise, etc.

It does not define document, window, fetch, setTimeout, console, or anything browser-specific.

URL: tc39.es/ecma262

The DOM Standard

Maintained by WHATWG (Web Hypertext Application Technology Working Group).

Defines the Document Object Model: what nodes are, how the tree is structured, how to create, find, modify, and delete elements, and how events work (bubbling, capturing, addEventListener, event objects).

Key interfaces defined by the DOM Standard:

  • Node, Element, Document, Text, Comment
  • EventTarget, Event, CustomEvent
  • NodeList, HTMLCollection
  • MutationObserver, AbortController

URL: dom.spec.whatwg.org

The HTML Specification

Maintained by WHATWG.

This is the largest and most comprehensive specification. It defines:

  • HTML elements and their attributes (<div>, <input>, <canvas>, etc.)
  • The window object and its properties
  • BOM objects: navigator, location, history, screen
  • Storage APIs: localStorage, sessionStorage
  • Timers: setTimeout, setInterval
  • Network APIs: fetch, XMLHttpRequest
  • Web Workers, Service Workers
  • The <canvas> element and its 2D/WebGL contexts
  • postMessage for cross-origin communication
  • Drag and Drop API
  • Web Storage and IndexedDB
  • The event loop, microtasks, and macrotasks
  • And much more

Essentially, everything in the browser environment that is not core JavaScript and not part of the DOM Standard is defined here.

URL: html.spec.whatwg.org

The CSS Object Model (CSSOM)

Maintained by the W3C.

Defines how JavaScript interacts with CSS: reading and modifying styles, computed styles, CSS rules, and style sheets.

// CSSOM in action
element.style.color = 'red';
getComputedStyle(element).fontSize;
document.styleSheets[0].cssRules;

URL: drafts.csswg.org/cssom

Other Specifications

Many browser APIs have their own dedicated specifications:

APISpecification
Fetchfetch.spec.whatwg.org
URLurl.spec.whatwg.org
Streamsstreams.spec.whatwg.org
Web ComponentsPart of DOM and HTML specs
Intersection ObserverW3C specification
Web AnimationsW3C specification
WebSocketPart of HTML spec
GeolocationW3C specification

How the Specifications Relate

┌──────────────────────────────────────────────────┐
│ Browser │
│ │
│ ┌───────────────────────────────────────────┐ │
│ │ HTML Specification │ │
│ │ window, navigator, location, history, │ │
│ │ setTimeout, fetch, storage, workers, │ │
│ │ canvas, drag-drop, event loop, ... │ │
│ │ │ │
│ │ ┌──────────────┐ ┌──────────────────┐ │ │
│ │ │ DOM Standard │ │ ECMAScript Spec │ │ │
│ │ │ │ │ │ │ │
│ │ │ document, │ │ let, const, │ │ │
│ │ │ elements, │ │ Array, Promise, │ │ │
│ │ │ events, │ │ Map, classes, │ │ │
│ │ │ nodes │ │ async/await, ... │ │ │
│ │ └──────────────┘ └──────────────────┘ │ │
│ │ │ │
│ │ ┌──────────┐ ┌─────────┐ ┌─────────┐ │ │
│ │ │ CSSOM │ │ Fetch │ │ URL │ │ │
│ │ └──────────┘ └─────────┘ └─────────┘ │ │
│ └───────────────────────────────────────────┘ │
└──────────────────────────────────────────────────┘

Where to Find Documentation

For day-to-day development, you do not need to read the raw specifications. Instead, use these resources:

  • MDN Web Docs (developer.mozilla.org): The best reference for all web APIs. Written for developers, with examples for every feature. Links to the relevant specification for each API.
  • Can I Use (caniuse.com): Browser compatibility tables for every feature.
  • The specifications themselves: Useful when you need to understand the exact behavior of an API, especially edge cases that MDN might not cover.

Seeing It All Together

Here is a practical example that uses the global object, DOM, and BOM together to build a simple page information display:

// Using the global object (window)
console.log('Window size:', window.innerWidth, 'x', window.innerHeight);

// Using the DOM (document)
const infoDiv = document.createElement('div');
infoDiv.style.padding = '20px';
infoDiv.style.fontFamily = 'monospace';
infoDiv.style.background = '#f5f5f5';
infoDiv.style.borderRadius = '8px';
infoDiv.style.margin = '20px';

// Using the BOM (navigator, location, screen)
const info = [
`Page Title: ${document.title}`,
`URL: ${location.href}`,
`Protocol: ${location.protocol}`,
`Browser Language: ${navigator.language}`,
`Online: ${navigator.onLine}`,
`Screen: ${screen.width}x${screen.height}`,
`Viewport: ${innerWidth}x${innerHeight}`,
`Pixel Ratio: ${devicePixelRatio}`,
`CPU Cores: ${navigator.hardwareConcurrency}`,
`History Length: ${history.length}`,
`Color Depth: ${screen.colorDepth}-bit`
];

infoDiv.innerHTML = info.map(line => `<div>${line}</div>`).join('');

// Using the DOM to add it to the page
document.body.prepend(infoDiv);

// Using BOM events
window.addEventListener('resize', () => {
console.log('New viewport size:', innerWidth, 'x', innerHeight);
});

window.addEventListener('online', () => {
console.log('Connection restored');
});

window.addEventListener('offline', () => {
console.log('Connection lost');
});

This small example touches all three layers: the global object (window, innerWidth, devicePixelRatio), the DOM (document.createElement, document.body.prepend), and the BOM (navigator, location, screen, history).

Summary

The browser is a host environment for JavaScript. It provides the JavaScript engine with APIs and objects that go far beyond the core language. These additions are organized into three main categories.

The window object sits at the top. It serves two roles: it is the JavaScript global object (all global variables and functions are its properties) and the browser window interface (providing dimensions, scroll position, timers, dialogs, and more). Variables declared with var become window properties, but let and const do not. The universal globalThis reference points to window in browsers.

The DOM (Document Object Model) represents the HTML page as a tree of objects. The document object is the entry point. Through the DOM, JavaScript can find, read, modify, create, and delete any element on the page. The DOM is defined by the DOM Standard maintained by WHATWG.

The BOM (Browser Object Model) covers everything the browser provides beyond the DOM: navigator for browser and device information, location for the current URL, history for navigation control, screen for display properties, plus fetch, setTimeout, localStorage, and many more. Most BOM features are defined by the HTML Specification, also maintained by WHATWG.

The core JavaScript language itself (variables, types, functions, classes, promises, arrays, etc.) is defined by the ECMAScript specification and works identically across all host environments. Everything else you use in the browser is provided by the browser environment and documented in the DOM Standard, HTML Specification, and various other web specifications.