window and document
Every browser page hands JavaScript two big global objects: window and document. Together they are your bridge from the language to the page. window represents the tab or frame your script is running in; document represents the HTML page loaded inside that window. Most of the browser APIs you will ever touch hang off one of these two objects.
window: the global object in browsers
In the browser, window is the global object. Any var or function declaration at the top level becomes a property of it, and built-ins like setTimeout, fetch and alert live on it too. You usually call them without the prefix because globals are implicit.
console.log(window === globalThis); // true in browsers
console.log(window.setTimeout === setTimeout); // true
// All these are window properties:
window.alert("hi");
window.fetch("/api/me");
window.location.href; // current URLdocument: the page itself
document is the root of the DOM — the tree of nodes that represents the HTML page. From it you can query elements, read attributes, change text, listen for events and create new nodes.
document.title; // <title> contents
document.documentElement; // <html>
document.head; // <head>
document.body; // <body>
document.URL; // same as location.href
const heading = document.querySelector("h1");
heading.textContent = "Updated!";
const items = document.querySelectorAll("li");
items.forEach((li, i) => (li.dataset.index = i));Key window properties you actually use
window.location— current URL, broken into parts; assign to it to navigate.window.navigator— info about the browser, language, online state, clipboard, geolocation.window.history— the session history of the tab; powerspushState/replaceState.window.screen— physical screen size; useful only for very specific cases.window.innerWidth/window.innerHeight— current viewport size in CSS pixels.window.scrollX/window.scrollY— current scroll offsets.window.localStorage/window.sessionStorage— small key/value stores.window.console— the developer console.
location: where am I?
const url = "https://example.com:8443/blog/post?id=42#comments";
// If location.href === url:
location.protocol; // "https:"
location.host; // "example.com:8443"
location.hostname; // "example.com"
location.port; // "8443"
location.pathname; // "/blog/post"
location.search; // "?id=42"
location.hash; // "#comments"
// Navigate:
location.href = "/login"; // full navigation
location.assign("/login"); // same as above
location.replace("/login"); // navigate without adding history entry
location.reload(); // refreshWe cover URL parsing, building and URLSearchParams in detail on the Location API page.
navigator: about the browser
navigator.language; // "en-GB" — preferred UI language navigator.languages; // ["en-GB", "en", "fr"] navigator.onLine; // boolean (best-effort, not reliable for connectivity tests) navigator.userAgent; // long string — mostly *not* what you want navigator.hardwareConcurrency; // logical CPU cores navigator.maxTouchPoints; // 0 on desktop, >0 on touch screens // Feature objects (may be undefined on older browsers): navigator.clipboard; // writeText / readText navigator.geolocation; // getCurrentPosition / watchPosition navigator.mediaDevices; // getUserMedia / enumerateDevices
Don't sniff userAgent to make decisions — feature-detect instead. See navigator for the long version.
history: the back/forward stack
history.length; // entries in this tab's history
history.back(); // same as the back button
history.forward(); // same as the forward button
history.go(-2); // jump backward two entries
// SPAs use these to change the URL without navigating:
history.pushState({ page: "about" }, "", "/about");
history.replaceState({ page: "home" }, "", "/");
addEventListener("popstate", (e) => {
console.log("URL changed:", location.pathname, e.state);
});This is the foundation every client-side router (Next.js, React Router, Vue Router) is built on. See History API.
Common window events
// Page is ready for scripts that need the DOM:
addEventListener("DOMContentLoaded", () => {
console.log("HTML parsed, DOM ready");
});
// All resources (images, stylesheets) finished loading:
addEventListener("load", () => console.log("everything loaded"));
// User is about to leave — return a string to prompt them (some browsers ignore it):
addEventListener("beforeunload", (e) => {
if (hasUnsavedWork) {
e.preventDefault();
e.returnValue = ""; // required for some browsers
}
});
// Viewport size or orientation changed:
addEventListener("resize", () => console.log(innerWidth, innerHeight));
// Network status — best-effort:
addEventListener("online", () => console.log("back online"));
addEventListener("offline", () => console.log("offline"));HTML parsed, DOM ready everything loaded
document.readyState
If your script runs after DOMContentLoaded has already fired, the event handler will never run. Check readyState and run immediately if needed.
function whenReady(fn) {
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", fn, { once: true });
} else {
fn();
}
}
whenReady(() => {
console.log("DOM is ready");
});window vs document — quick mental model
windowis the tab/frame: timers, network, storage, history, location, viewport.documentis the page inside it: HTML elements, text, attributes, events that bubble through the DOM.Both exist only in browsers. In Node use
globalThisinstead ofwindow; there is nodocument.