Skip to content

浏览器对象模型(BOM)

一、BOM概述

1.1 什么是BOM?

BOM (Browser Object Model) 提供了独立于内容而与浏览器窗口进行交互的对象,核心对象是window。

javascript
// BOM的层级结构
window
  ├── document (DOM)
  ├── location (URL定位与导航)
  ├── navigation (浏览器信息)
  ├── screen (屏幕信息)
  ├── history (历史记录)
  └── frames (框架)

1.2 BOM与DOM的区别

javascript
// DOM - 文档对象模型
document.querySelector('.className');
document.getElementById('myId');

// BOM - 浏览器对象模型
window.innerHeight;
window.location.href;

二、Window对象详解

2.1 全局作用域

javascript
// window作为全局对象
var globalVar = 'global';
function globalFunc() { }

console.log(window.globalVar);     // 'global'
console.log(window.globalFunc);    // ƒ globalFunc() { }

// 但let和const声明的变量不会挂载到window
let letVar = 'let';
console.log(window.letVar);        // undefined

2.2 窗口操作

javascript
// 窗口大小
const pageWidth = window.innerWidth 
    || document.documentElement.clientWidth 
    || document.body.clientWidth;

// 视口位置
function scrollToTop() {
    if (window.pageYOffset) {
        window.scrollTo({
            top: 0,
            behavior: 'smooth'
        });
    }
}

// 窗口打开与关闭
const popup = window.open('about:blank', 'popup', `
    width=400,
    height=400,
    left=${(screen.width - 400) / 2},
    top=${(screen.height - 400) / 2}
`);

// 安全检查
if (popup && !popup.closed) {
    popup.document.write('<h1>Popup Content</h1>');
}

三、Location对象高级应用

3.1 URL解析与操作

javascript
// URL解析器
class URLParser {
    constructor(url) {
        this.parser = document.createElement('a');
        this.parser.href = url;
    }
    
    get protocol() {
        return this.parser.protocol.replace(':', '');
    }
    
    get hostname() {
        return this.parser.hostname;
    }
    
    get query() {
        const params = new URLSearchParams(this.parser.search);
        return Object.fromEntries(params.entries());
    }
}

// 使用示例
const parser = new URLParser('https://example.com:8080/path?name=test#hash');
console.log(parser.protocol);  // 'https'
console.log(parser.query);     // { name: 'test' }

3.2 导航增强

javascript
class Navigator {
    static pushState(url, title = '', state = {}) {
        if (window.history.pushState) {
            window.history.pushState(state, title, url);
            return true;
        }
        location.href = url;
        return false;
    }
    
    static redirect(url, options = {}) {
        const { 
            replace = false,
            timeout = 0,
            callback
        } = options;
        
        setTimeout(() => {
            if (replace) {
                location.replace(url);
            } else {
                location.href = url;
            }
            callback?.();
        }, timeout);
    }
}

四、Navigator对象与特性检测

4.1 浏览器检测

javascript
class BrowserDetector {
    static get userAgent() {
        return navigator.userAgent;
    }
    
    static get isChrome() {
        return /Chrome/.test(this.userAgent) && /Google/.test(navigator.vendor);
    }
    
    static get isSafari() {
        return /Safari/.test(this.userAgent) && /Apple/.test(navigator.vendor);
    }
    
    static get isFirefox() {
        return /Firefox/.test(this.userAgent);
    }
    
    static get isEdge() {
        return /Edg/.test(this.userAgent);
    }
    
    static get isMobile() {
        return /Mobile/.test(this.userAgent);
    }
}

4.2 特性检测

javascript
class FeatureDetector {
    static checkAPI(api) {
        return api in window;
    }
    
    static get features() {
        return {
            localStorage: this.checkAPI('localStorage'),
            serviceWorker: this.checkAPI('serviceWorker'),
            geolocation: this.checkAPI('navigator.geolocation'),
            webGL: () => {
                try {
                    return !!document.createElement('canvas')
                        .getContext('webgl');
                } catch(e) {
                    return false;
                }
            }
        };
    }
}

五、Screen对象与响应式设计

javascript
class ScreenHelper {
    static get screenInfo() {
        return {
            width: screen.width,
            height: screen.height,
            availWidth: screen.availWidth,
            availHeight: screen.availHeight,
            colorDepth: screen.colorDepth,
            orientation: screen.orientation.type
        };
    }
    
    static watchOrientation(callback) {
        screen.orientation.addEventListener('change', () => {
            callback(screen.orientation.type);
        });
    }
}

六、History API与状态管理

javascript
class HistoryManager {
    constructor() {
        this.handlers = new Map();
        window.addEventListener('popstate', this.handlePopState.bind(this));
    }
    
    push(url, state = {}) {
        history.pushState(state, '', url);
        this.handleStateChange(state);
    }
    
    replace(url, state = {}) {
        history.replaceState(state, '', url);
        this.handleStateChange(state);
    }
    
    registerHandler(key, handler) {
        this.handlers.set(key, handler);
    }
    
    handlePopState(event) {
        this.handleStateChange(event.state);
    }
    
    handleStateChange(state) {
        if (!state) return;
        
        for (const [key, handler] of this.handlers) {
            if (state[key]) {
                handler(state[key]);
            }
        }
    }
}

// 使用示例
const historyManager = new HistoryManager();

historyManager.registerHandler('page', (pageData) => {
    console.log('Page changed:', pageData);
});

historyManager.push('/new-page', {
    page: { id: 1, title: 'New Page' }
});

七、最佳实践

7.1 性能优化

javascript
// 防抖动的resize监听
function debounceResize(callback, delay = 250) {
    let timeoutId;
    
    window.addEventListener('resize', () => {
        clearTimeout(timeoutId);
        timeoutId = setTimeout(() => {
            callback({
                width: window.innerWidth,
                height: window.innerHeight
            });
        }, delay);
    });
}

7.2 安全考虑

javascript
// 安全的window.open
function safeWindowOpen(url, name, features) {
    // 检查URL
    if (!/^https?:\/\//i.test(url)) {
        throw new Error('Invalid URL protocol');
    }
    
    const popup = window.open(url, name, features);
    
    // 检查popup是否被阻止
    if (popup === null) {
        console.warn('Popup was blocked');
        return null;
    }
    
    // 添加安全限制
    popup.opener = null;
    
    return popup;
}

总结

  1. BOM提供了与浏览器交互的核心API
  2. 正确使用BOM可以:
    • 实现复杂的导航逻辑
    • 管理浏览器窗口
    • 检测浏览器特性
    • 响应用户操作
  3. 开发中需注意:
    • 浏览器兼容性
    • 性能优化
    • 安全限制
    • 用户体验