The Window Object
In a browser, window is the global object — the root from which every other browser feature hangs. It represents the tab or frame your script runs in, holds all your global variables and functions, and serves as the entry point to the Browser Object Model (BOM): things like location, history, navigator, and localStorage. Understanding window is understanding the environment your code lives in.
window is the global object
Every global you declare in browser script becomes a property of window. When you read a bare identifier like alert or setTimeout, the engine resolves it against the global object. That is why alert(...) and window.alert(...) are the same call.
function greet() {
return "hi";
}
console.log(window.greet === greet); // true
console.log("setTimeout" in window); // true
console.log(window.console === console); // true
Output:
true
true
true
There is one important nuance: var declarations and function declarations at the top level become window properties, but let, const, and class do not. They live in a separate lexical scope, so they stay off the global object.
var legacy = 1;
let modern = 2;
console.log(window.legacy); // 1
console.log(window.modern); // undefined
Output:
1
undefined
Avoid attaching things to
windowon purpose. Global state is hard to track and collides easily across scripts. Prefer modules (import/export), which keep their bindings private.
globalThis: one name everywhere
The catch with window is that it only exists in browsers. In Node.js the global object is global; in a Web Worker it is self. ES2020 introduced globalThis as a single, portable reference to the global object in any environment.
// Works in browsers, Node, workers, Deno — everywhere.
globalThis.appConfig = { debug: true };
console.log(globalThis === window); // true (in a browser tab)
| Environment | Global object name | globalThis works? |
|---|---|---|
| Browser (main thread) | window (also self) | Yes |
| Web Worker | self | Yes |
| Node.js | global | Yes |
| Deno | — | Yes |
Reach for globalThis whenever you write code that might run outside a browser. Reserve window for code that is genuinely browser-only.
Viewport and scroll properties
window exposes live measurements of the viewport and the current scroll position. These update as the user resizes the tab or scrolls, so reading them always gives the current value.
| Property | Description |
|---|---|
innerWidth / innerHeight | Viewport size in CSS pixels, including scrollbars. |
outerWidth / outerHeight | The whole browser window, including chrome. |
scrollX / scrollY | How far the document has scrolled, in pixels. |
devicePixelRatio | Physical pixels per CSS pixel (2 on most retina screens). |
console.log(`Viewport: ${window.innerWidth} x ${window.innerHeight}`);
console.log(`Scrolled down: ${window.scrollY}px`);
// Programmatic scrolling, with smooth animation:
window.scrollTo({ top: 0, behavior: "smooth" });
The demo below reads these values live. Resize the result pane and scroll it to watch the numbers change.
<!DOCTYPE html>
<html>
<head>
<style>
body { font-family: system-ui, sans-serif; margin: 0; padding: 24px; height: 1500px; }
#panel {
position: fixed; top: 12px; left: 12px;
background: #1e293b; color: #e2e8f0;
padding: 14px 18px; border-radius: 8px;
font-family: monospace; line-height: 1.6;
}
</style>
</head>
<body>
<div id="panel"></div>
<p>Scroll and resize this pane to see <code>window</code> update.</p>
<script>
const panel = document.querySelector("#panel");
function render() {
panel.textContent =
`innerWidth: ${window.innerWidth}\n` +
`innerHeight: ${window.innerHeight}\n` +
`scrollY: ${Math.round(window.scrollY)}\n` +
`dpr: ${window.devicePixelRatio}`;
}
render();
window.addEventListener("resize", render);
window.addEventListener("scroll", render);
</script>
</body>
</html>
Dialog methods: alert, confirm, prompt
window provides three blocking dialogs. They pause script execution until the user responds, which makes them handy for quick demos but unsuitable for production UI — they freeze the whole page and cannot be styled.
| Method | Returns | Use |
|---|---|---|
alert(msg) | undefined | Show a message with an OK button. |
confirm(msg) | boolean | Ask a yes/no question; true if OK. |
prompt(msg, default) | string | null | Ask for text input; null if cancelled. |
alert("Saved successfully.");
if (confirm("Delete this file?")) {
console.log("user confirmed");
}
const name = prompt("What is your name?", "Guest");
console.log(name === null ? "cancelled" : `Hello, ${name}`);
Try all three in the interactive example below.
<!DOCTYPE html>
<html>
<head>
<style>
body { font-family: system-ui, sans-serif; padding: 24px; }
button { font-size: 1rem; padding: 8px 14px; margin-right: 8px; cursor: pointer; }
#out { margin-top: 16px; font-family: monospace; }
</style>
</head>
<body>
<button id="a">alert</button>
<button id="c">confirm</button>
<button id="p">prompt</button>
<div id="out">Click a button.</div>
<script>
const out = document.querySelector("#out");
document.querySelector("#a").addEventListener("click", () => {
alert("This is an alert.");
out.textContent = "alert() returned undefined";
});
document.querySelector("#c").addEventListener("click", () => {
const ok = confirm("Are you sure?");
out.textContent = `confirm() returned ${ok}`;
});
document.querySelector("#p").addEventListener("click", () => {
const value = prompt("Type something:", "hello");
out.textContent = `prompt() returned ${JSON.stringify(value)}`;
});
</script>
</body>
</html>
Dialogs are synchronous and modal: nothing else runs while one is open. Browsers also suppress them in some contexts (e.g. during page unload, or repeated dialogs). Build real confirmations with your own DOM-based modals.
Other useful window members
Beyond globals and dialogs, window is the namespace for much of the BOM and several events worth knowing.
// BOM entry points hanging off window:
console.log(window.location.href); // current URL
console.log(window.navigator.language); // e.g. "en-US"
// The DOMContentLoaded vs load distinction:
window.addEventListener("load", () => {
console.log("all assets, including images, are ready");
});
// Open and reference other windows/tabs:
const popup = window.open("https://example.com", "_blank");
Best Practices
- Prefer
globalThisoverwindowin code that may run in Node, workers, or other runtimes. - Keep globals to a minimum; use ES modules instead of attaching values to
window. - Remember that
let,const, andclassdo not createwindowproperties — onlyvarand function declarations do. - Treat
window.innerWidth/scrollYas live reads; cache them in a variable if you reference them many times in a tight loop. - Throttle or debounce
resizeandscrollhandlers, which fire very frequently. - Use
alert/confirm/promptonly for prototypes; they block the thread and cannot be styled — ship custom modals instead.