

什麼是 BOM?
你有沒有想過,為什麼 JavaScript 可以控制瀏覽器的網址列、偵測使用者的螢幕大小、甚至存取剪貼簿?這些都不是「網頁內容」的一部分,而是瀏覽器本身提供的能力。BOM 就是這座橋樑——搞懂它,你才真正掌握了「JavaScript 在瀏覽器裡能做到哪些事」。
BOM(Browser Object Model,瀏覽器物件模型)是瀏覽器提供的 API,讓 JavaScript 可以與瀏覽器本身互動,而不僅僅是網頁內容。
┌─────────────────────────────────────────────────┐
│ window │
│ ┌───────────┐ ┌───────────┐ ┌───────────┐ │
│ │ document │ │ location │ │ navigator │ │
│ │ (DOM) │ │ (URL) │ │ (瀏覽器) │ │
│ └───────────┘ └───────────┘ └───────────┘ │
│ ┌───────────┐ ┌───────────┐ ┌───────────┐ │
│ │ history │ │ screen │ │ localStorage│ │
│ │ (歷史) │ │ (螢幕) │ │ (儲存) │ │
│ └───────────┘ └───────────┘ └───────────┘ │
└─────────────────────────────────────────────────┘
window 物件
window 是瀏覽器的全域物件,所有全域變數和函數都是它的屬性。
// 視窗尺寸
window.innerWidth; // 視窗內部寬度(不含工具列)
window.innerHeight; // 視窗內部高度
window.outerWidth; // 視窗外部寬度(含工具列)
window.outerHeight; // 視窗外部高度
// 視窗位置
window.screenX; // 視窗左上角 X 座標
window.screenY; // 視窗左上角 Y 座標
// 滾動位置
window.scrollX; // 水平滾動距離
window.scrollY; // 垂直滾動距離
window.pageXOffset; // 同 scrollX
window.pageYOffset; // 同 scrollY
// 滾動方法
window.scrollTo(0, 100);
window.scrollTo({ top: 100, behavior: 'smooth' });
window.scrollBy(0, 50); // 相對滾動對話框
// 警告框
alert('Hello!');
// 確認框
const confirmed = confirm('確定要刪除嗎?');
if (confirmed) { /* 執行刪除 */ }
// 輸入框
const name = prompt('請輸入姓名', '預設值');
// 注意:這些方法會阻塞 JavaScript 執行
// 現代應用通常使用自訂 Modal 代替計時器
// setTimeout - 延遲執行(一次)
const timeoutId = setTimeout(() => {
console.log('3 秒後執行');
}, 3000);
clearTimeout(timeoutId); // 取消
// setInterval - 定期執行
const intervalId = setInterval(() => {
console.log('每秒執行');
}, 1000);
clearInterval(intervalId); // 取消
// requestAnimationFrame - 動畫用(約 60fps)
function animate() {
// 更新動畫
requestAnimationFrame(animate);
}
requestAnimationFrame(animate);開啟新視窗
// 開啟新視窗
const newWindow = window.open(
'https://example.com',
'_blank',
'width=800,height=600'
);
// 關閉視窗
newWindow.close();
// 檢查視窗是否關閉
if (newWindow.closed) {
console.log('視窗已關閉');
}知道了 window 是什麼之後,你可能會想問:那網址列呢?怎麼用 JS 讀取或改變當前的 URL?這就是 location 的工作。
location 物件
location 包含當前 URL 的資訊,也可以用來導航。
// URL: https://example.com:8080/path/page.html?id=123#section
location.href; // 完整 URL
location.protocol; // "https:"
location.host; // "example.com:8080"
location.hostname; // "example.com"
location.port; // "8080"
location.pathname; // "/path/page.html"
location.search; // "?id=123"
location.hash; // "#section"
location.origin; // "https://example.com:8080"
// 導航
location.href = 'https://example.com'; // 跳轉(會留下歷史)
location.assign('https://example.com'); // 同上
location.replace('https://example.com'); // 跳轉(不留歷史)
location.reload(); // 重新載入
location.reload(true); // 強制從伺服器載入
// 解析 Query String
const params = new URLSearchParams(location.search);
params.get('id'); // "123"
params.has('id'); // true
params.set('id', '456');
params.toString(); // "id=456"history 物件
history 提供瀏覽歷史的操作。
// 瀏覽歷史
history.length; // 歷史記錄數量
history.back(); // 上一頁
history.forward(); // 下一頁
history.go(-2); // 往前兩頁
history.go(1); // 往後一頁
// HTML5 History API(SPA 路由用)
history.pushState({ page: 1 }, 'Title', '/page1');
history.replaceState({ page: 2 }, 'Title', '/page2');
// 監聽歷史變化
window.addEventListener('popstate', (event) => {
console.log('State:', event.state);
});OK,到目前為止我們學了怎麼控制視窗、操作網址和歷史紀錄。但有時候你需要知道的是使用者的環境——他用什麼瀏覽器?有沒有網路?這就是 navigator 的守備範圍。
navigator 物件
navigator 提供瀏覽器和裝置資訊。
// 瀏覽器資訊
navigator.userAgent; // 瀏覽器識別字串
navigator.language; // 瀏覽器語言 "zh-TW"
navigator.languages; // 偏好語言列表
navigator.platform; // 作業系統平台
navigator.cookieEnabled; // Cookie 是否啟用
navigator.onLine; // 是否連線
// 監聯網狀態
window.addEventListener('online', () => console.log('上線了'));
window.addEventListener('offline', () => console.log('離線了'));
// 剪貼簿 API
await navigator.clipboard.writeText('複製的文字');
const text = await navigator.clipboard.readText();
// 地理位置 API
navigator.geolocation.getCurrentPosition(
(position) => {
console.log(position.coords.latitude);
console.log(position.coords.longitude);
},
(error) => console.error(error)
);
// 震動 API(行動裝置)
navigator.vibrate(200); // 震動 200ms
navigator.vibrate([100, 50, 100]); // 震動模式
// 分享 API
if (navigator.share) {
navigator.share({
title: '標題',
text: '內容',
url: 'https://example.com'
});
}screen 物件
screen 提供螢幕資訊。
screen.width; // 螢幕寬度
screen.height; // 螢幕高度
screen.availWidth; // 可用寬度(扣除工具列)
screen.availHeight; // 可用高度
screen.colorDepth; // 色彩深度
screen.pixelDepth; // 像素深度
screen.orientation; // 螢幕方向
// 監聽螢幕方向變化
screen.orientation.addEventListener('change', () => {
console.log(screen.orientation.type); // "portrait-primary" | "landscape-primary"
});Storage API
// localStorage - 永久儲存
localStorage.setItem('key', 'value');
localStorage.getItem('key');
localStorage.removeItem('key');
localStorage.clear();
// sessionStorage - 分頁關閉即清除
sessionStorage.setItem('key', 'value');
// 儲存物件需要序列化
localStorage.setItem('user', JSON.stringify({ name: 'John' }));
const user = JSON.parse(localStorage.getItem('user'));
// 監聽儲存變化(跨分頁同步)
window.addEventListener('storage', (event) => {
console.log(event.key, event.oldValue, event.newValue);
});BOM vs DOM
| 項目 | BOM | DOM |
|---|---|---|
| 操作對象 | 瀏覽器 | 網頁內容 |
| 根物件 | window | document |
| 標準化 | 部分 | W3C 標準 |
| 功能 | 視窗、導航、儲存 | 元素操作、事件 |