window と document の違い
window は「ブラウザタブ(ウィンドウ)そのもの」を表す最上位のオブジェクトです。タイマー、画面サイズ、スクロール、イベント、ストレージ、ネットワークなど“環境”全体を扱います。document は「そのウィンドウ内の現在のページ(DOM ツリー)の入り口」を表し、HTML 要素の取得・作成・挿入・削除など“ページの中身”を扱います。ここが重要です:window は「器」、document は「器の中の文書」。UIの見た目や要素を変えるときは document、タブ全体の状態やイベントを扱うときは window を使います。
役割の直感と代表的な操作
window はタブのライフサイクルや外部とのやり取り、表示領域の情報を扱います。例として、画面サイズを取る、スクロール位置を読む、タイマーで処理を予約する、ロード完了を待つなどが得意です。
// 画面サイズとスクロール
console.log(window.innerWidth, window.innerHeight); // 表示領域の幅・高さ
console.log(window.scrollX, window.scrollY); // スクロール位置
// タイマー
const id = window.setTimeout(() => console.log("遅延実行"), 500);
window.clearTimeout(id);
// ウィンドウ全体のイベント
window.addEventListener("resize", () => console.log("サイズ変化"));
window.addEventListener("load", () => console.log("外部リソースまで読み込み完了"));
JavaScriptdocument は DOM ツリー(要素・テキスト・コメント)の根で、要素の取得や生成を行います。ページの中身を操作するときは document を起点にします。
// 要素取得
const title = document.querySelector("#title");
title.textContent = "ようこそ";
// 要素生成・挿入
const p = document.createElement("p");
p.textContent = "説明文";
document.body.append(p);
JavaScriptここが重要です:画面のサイズ・タブのイベント・タイマーは window、要素・テキスト・属性・クラスの操作は document。
イベントの違いと使い分け
window のイベントは「タブ全体」に関わります。resize、scroll、load、visibilitychange などが典型です。ページの読み込み状況や表示領域の変化に反応したいときに使います。
window.addEventListener("visibilitychange", () => {
const hidden = document.hidden;
console.log(hidden ? "非表示" : "表示中");
});
JavaScriptdocument のイベントは「DOM に対する操作」に向きます。DOMContentLoaded(DOM 構築完了)、クリックや入力などの UI イベントの委譲、選択・フォーカスなど要素中心の反応を設計できます。
document.addEventListener("DOMContentLoaded", () => {
const form = document.querySelector("form");
form.addEventListener("submit", (e) => {
e.preventDefault();
console.log("送信を制御");
});
});
JavaScriptここが重要です:初期化は DOMContentLoaded(document)で要素取得とイベント登録、画像サイズ依存などリソース完了が必要なら load(window)を使うのが定石です。
グローバル変数・スコープの勘所
ブラウザでは、トップレベルで var で宣言した変数や関数宣言は window のプロパティになります。一方、let/const はグローバルレキシカル環境に置かれ、window にぶら下がりません。無意識にグローバルを作ると衝突や上書きの原因になります。
var legacy = 1; // window.legacy として公開される
let modern = 2; // window.modern は存在しない
console.log(window.legacy); // 1
console.log("modern" in window); // false
JavaScriptここが重要です:グローバルに依存せず、モジュール(type=”module”)や名前空間で管理すると安全です。window を汚さない設計が保守性を高めます。
画面情報とレイアウト(window)と DOM 構造(document)
画面の「枠」を知りたいときは window、ページの「中身」を知りたいときは document を使います。リサイズやスクロールに応じてクラスを書き換えたり、ビューポート判定をして DOM を更新するのが定番パターンです。
// ビューポート幅に応じてレイアウトクラスを切り替え
function updateLayout() {
const wide = window.innerWidth >= 768;
document.body.classList.toggle("is-wide", wide);
}
window.addEventListener("resize", updateLayout);
document.addEventListener("DOMContentLoaded", updateLayout);
JavaScriptここが重要です:window で環境を読み、document で要素を変える。役割を分離すると、処理の見通しがよくなります。
実践例:ナビ固定と初期化の正攻法
ヘッダーをスクロールで固定する UI を考えます。スクロールイベントは window、クラス切り替えは document(要素)で行います。初期化は DOMContentLoaded で安全に。
document.addEventListener("DOMContentLoaded", () => {
const header = document.querySelector(".header");
const threshold = 100;
function onScroll() {
const fixed = window.scrollY > threshold;
header.classList.toggle("is-fixed", fixed);
}
window.addEventListener("scroll", onScroll);
onScroll(); // 初期状態を反映
});
JavaScriptここが重要です:イベントは「誰が発火させるか(window)」、反映は「どこを変えるか(document の要素)」。この分担が読みやすさ・拡張性を生みます。
まとめ
window はブラウザタブの“環境”全体、document はその中の“文書(DOM)”です。サイズ・スクロール・ロード・タイマーなどは window、要素の取得・生成・挿入・属性やクラスの変更は document。初期化は DOMContentLoaded(document)で、リソース完了が必要なら load(window)を使い分けます。環境を読むのが window、中身を変えるのが document——このシンプルな軸を体に入れると、DOM 操作は途端に迷いなく、意図通りに書けるようになります。
