Article

BOM 操作速查文档

更新于:2026-07-08

一、BOM基础概念

1.1 BOM简介与核心对象

概念名称说明注意事项
BOM (Browser Object Model)浏览器对象模型,是浏览器提供的用于处理文档(document)之外的所有内容的对象集合,用于描述浏览器本身及其相关功能BOM没有统一的官方标准,各浏览器厂商自行实现,可能存在兼容性问题
BOM与DOM的区别DOM(Document Object Model)处理网页内容的标准接口,关注HTML/XML文档结构;BOM处理浏览器窗口和框架,关注浏览器环境本身document对象实际上是window对象的子对象(window.document),体现了BOM与DOM的关系
BOM核心功能提供控制浏览器窗口、获取屏幕信息、操作历史记录、访问浏览器信息等功能BOM使JavaScript能够与浏览器环境进行交互,而不仅限于操作页面内容
BOM主要对象组成包含window、location、navigator、screen、history等核心对象这些对象都是window对象的属性,可以直接通过window对象访问

1.2 window对象概述

概念名称说明注意事项
window对象BOM的核心对象,表示浏览器的一个实例,是所有BOM对象的顶层容器所有全局JavaScript变量、函数和对象都会自动成为window对象的成员
双重角色既是JavaScript访问浏览器窗口的接口,又是ECMAScript规定的Global(全局)对象在全局作用域中声明的任何变量、函数都会变成window对象的属性和方法
全局作用域由于window扮演Global对象角色,可以直接省略window前缀调用其属性和方法例如:alert()等价于window.alert(),document等价于window.document
对象层次结构window对象包含其他BOM对象:document、location、navigator、screen、history这些对象可以通过window.location或直接location方式访问
HTML文档对应关系每个HTML文档对应一个window对象实例在多窗口或多iframe场景下,每个窗口/iframe都有独立的window对象

二、核心BOM对象详解

2.1 window对象常用属性与方法

方法/属性名称语法用途代码示例注意事项
alert()window.alert(message)显示警告对话框alert("Hello World");阻塞后续代码执行,直到用户点击确定;现代浏览器可能限制频繁调用
confirm()window.confirm(message)显示确认对话框,返回布尔值if(confirm("确定删除?")) { /* 删除操作 */ }返回true(确定)或false(取消);同样会阻塞代码执行
prompt()window.prompt(message, default)显示提示输入对话框,返回用户输入的字符串let name = prompt("请输入姓名", "匿名");返回用户输入内容或null(取消);第二个参数为默认值
open()window.open(url, target, features, replace)打开新窗口或标签页let newWin = window.open("https://example.com", "_blank");可能被浏览器弹窗拦截器阻止;返回新窗口的window引用
close()window.close()关闭当前窗口window.close();只能关闭由window.open()打开的窗口,不能关闭用户手动打开的窗口
resizeTo()window.resizeTo(width, height)调整窗口大小window.resizeTo(800, 600);大多数现代浏览器出于安全考虑已禁用此方法
moveTo()window.moveTo(x, y)移动窗口到指定位置window.moveTo(100, 100);大多数现代浏览器出于安全考虑已禁用此方法
innerWidth/innerHeightwindow.innerWidth / window.innerHeight获取视口(viewport)宽度和高度console.log(window.innerWidth);包含滚动条在内的视口尺寸,不包含浏览器UI
outerWidth/outerHeightwindow.outerWidth / window.outerHeight获取浏览器窗口外部尺寸console.log(window.outerWidth);包含浏览器UI(地址栏、工具栏等)的完整窗口尺寸
scrollX/scrollYwindow.scrollX / window.scrollY获取页面水平/垂直滚动偏移量console.log("已滚动: " + window.scrollY + "px");等同于pageXOffset/pageYOffset,IE9+支持
scrollTo()window.scrollTo(x, y)window.scrollTo(options)滚动到指定位置window.scrollTo(0, 100);window.scrollTo({top: 100, behavior: 'smooth'});options参数支持behavior:‘smooth’实现平滑滚动
scrollBy()window.scrollBy(x, y)window.scrollBy(options)相对于当前位置滚动指定距离window.scrollBy(0, 100);同样支持平滑滚动选项

2.2 location对象(URL操作)

方法/属性名称语法用途代码示例注意事项
hreflocation.href获取或设置完整URLconsole.log(location.href); location.href = "https://example.com";设置href会触发页面跳转,等同于assign()方法
protocollocation.protocol获取URL协议console.log(location.protocol); // "https:"返回值包含冒号,如”http:”、“https:“
hostlocation.host获取主机名和端口console.log(location.host); // "example.com:8080"包含端口号(如果有)
hostnamelocation.hostname获取主机名console.log(location.hostname); // "example.com"不包含端口号
portlocation.port获取端口号console.log(location.port); // "8080"如果使用默认端口(80/443),可能返回空字符串
pathnamelocation.pathname获取路径部分console.log(location.pathname); // "/path/page.html"从域名后的第一个斜杠开始
searchlocation.search获取查询字符串console.log(location.search); // "?id=123&name=test"包含问号,可配合URLSearchParams解析
hashlocation.hash获取锚点(hash)console.log(location.hash); // "#section1"包含井号,改变hash不会触发页面重新加载
assign()location.assign(url)加载新文档location.assign("https://example.com");会在历史记录中添加新条目,用户可后退
replace()location.replace(url)替换当前文档location.replace("https://example.com");不会在历史记录中添加新条目,用户无法后退到原页面
reload()location.reload(forcedReload)重新加载当前页面location.reload();location.reload(true);参数为true时强制从服务器重新加载(忽略缓存)
toString()location.toString()返回href的字符串表示console.log(location.toString());等同于location.href

2.3 navigator对象(浏览器信息)

方法/属性名称语法用途代码示例注意事项
userAgentnavigator.userAgent获取用户代理字符串console.log(navigator.userAgent);可用于检测浏览器类型,但容易被伪造,不推荐作为唯一检测依据
platformnavigator.platform获取操作系统平台console.log(navigator.platform); // "Win32"、"MacIntel"等返回值可能不准确,现代浏览器出于隐私考虑可能返回通用值
languagenavigator.language获取浏览器首选语言console.log(navigator.language); // "zh-CN"、"en-US"等返回用户的首选语言设置
languagesnavigator.languages获取用户偏好的语言列表console.log(navigator.languages); // ["zh-CN", "en-US"]返回数组,按偏好程度排序
onLinenavigator.onLine检测网络连接状态console.log(navigator.onLine); // true/false只能检测设备是否连接到网络,不能保证实际互联网连接
geolocationnavigator.geolocation访问地理位置APInavigator.geolocation.getCurrentPosition(success, error);需要用户授权,仅在安全上下文(HTTPS)中可用
cookieEnablednavigator.cookieEnabled检测Cookie是否启用console.log(navigator.cookieEnabled); // true/false返回布尔值,指示浏览器是否启用了Cookie
hardwareConcurrencynavigator.hardwareConcurrency获取CPU逻辑处理器数量console.log(navigator.hardwareConcurrency); // 4、8等可用于性能优化,但出于隐私考虑可能返回较低值
maxTouchPointsnavigator.maxTouchPoints获取设备支持的最大触摸点数console.log(navigator.maxTouchPoints); // 0(非触摸设备)、5、10等用于检测设备触摸能力
sendBeacon()navigator.sendBeacon(url, data)在页面卸载时发送数据navigator.sendBeacon("/log", analyticsData);保证数据可靠发送,即使页面正在关闭

2.4 screen对象(屏幕信息)

方法/属性名称语法用途代码示例注意事项
widthscreen.width获取屏幕宽度(像素)console.log(screen.width); // 1920返回物理屏幕的总宽度,不受缩放影响
heightscreen.height获取屏幕高度(像素)console.log(screen.height); // 1080返回物理屏幕的总高度,不受缩放影响
availWidthscreen.availWidth获取可用屏幕宽度console.log(screen.availWidth); // 1920减去操作系统UI(如任务栏)后的可用宽度
availHeightscreen.availHeight获取可用屏幕高度console.log(screen.availHeight); // 1040减去操作系统UI后的可用高度
colorDepthscreen.colorDepth获取屏幕色深console.log(screen.colorDepth); // 24表示每个像素的颜色位数,通常为24或32
pixelDepthscreen.pixelDepth获取屏幕像素深度console.log(screen.pixelDepth); // 24通常与colorDepth相同
orientationscreen.orientation获取屏幕方向信息console.log(screen.orientation.type); // "landscape-primary"返回Orientation对象,包含type和angle属性
lockOrientation()screen.lockOrientation(orientations)锁定屏幕方向screen.lockOrientation('landscape');已废弃,现代浏览器使用screen.orientation.lock()替代
unlockOrientation()screen.unlockOrientation()解锁屏幕方向screen.unlockOrientation();已废弃,现代浏览器使用screen.orientation.unlock()替代

2.5 history对象(浏览历史)

方法/属性名称语法用途代码示例注意事项
lengthhistory.length获取历史记录条目数console.log(history.length);返回当前会话中的历史记录数量
back()history.back()后退到上一个页面history.back();等同于点击浏览器后退按钮
forward()history.forward()前进到下一个页面history.forward();等同于点击浏览器前进按钮
go()history.go(delta)在历史记录中跳转history.go(-1); // 后退一步 history.go(2); // 前进两步参数为整数,负数后退,正数前进
pushState()history.pushState(state, title, url)添加新历史记录条目history.pushState({page: 1}, "Page 1", "/page1");不会触发页面刷新,用于SPA路由;state可存储任意数据
replaceState()history.replaceState(state, title, url)替换当前历史记录条目history.replaceState({page: 2}, "Page 2", "/page2");同样不会触发页面刷新,但替换当前条目而非添加新条目
statehistory.state获取当前历史记录条目的状态对象console.log(history.state);返回通过pushState/replaceState设置的state对象
popstate事件window.addEventListener('popstate', handler)监听历史记录变化window.addEventListener('popstate', function(e) { console.log(e.state); });仅在用户导航(后退/前进)时触发,pushState/replaceState不会触发

三、窗口与对话框操作

3.1 窗口控制方法

方法/属性名称语法用途代码示例注意事项
open()window.open(url, name, features, replace)打开新窗口或标签页const newWin = window.open('https://example.com', '_blank', 'width=600,height=400');大多数浏览器会拦截非用户触发的弹窗;返回新窗口的window引用
close()window.close()关闭当前窗口window.close();只能关闭由window.open()创建的窗口,不能关闭用户手动打开的窗口
focus()window.focus()将窗口置于前台并获得焦点newWin.focus();可能被浏览器安全策略限制,特别是在移动设备上
blur()window.blur()使窗口失去焦点newWin.blur();现代浏览器通常忽略此方法,出于用户体验考虑
resizeTo()window.resizeTo(width, height)将窗口调整到指定尺寸newWin.resizeTo(800, 600);大多数现代浏览器已禁用此功能,仅对window.open()创建的窗口可能有效
resizeBy()window.resizeBy(deltaX, deltaY)相对于当前尺寸调整窗口大小newWin.resizeBy(100, -50);同resizeTo(),现代浏览器通常禁用
moveTo()window.moveTo(x, y)移动窗口到屏幕指定坐标newWin.moveTo(100, 100);几乎所有现代浏览器都已禁用此功能
moveBy()window.moveBy(deltaX, deltaY)相对于当前位置移动窗口newWin.moveBy(50, 50);同moveTo(),现代浏览器通常禁用
scroll()window.scroll(x, y)滚动到页面指定位置window.scroll(0, 100);已被scrollTo()替代,但仍然可用
scrollTo()window.scrollTo(x, y)window.scrollTo(options)滚动到页面指定位置window.scrollTo({top: 100, left: 0, behavior: 'smooth'});支持平滑滚动,options参数提供更多控制选项
scrollBy()window.scrollBy(x, y)window.scrollBy(options)相对于当前位置滚动window.scrollBy({top: 100, behavior: 'smooth'});同样支持平滑滚动选项
print()window.print()打印当前页面window.print();会触发浏览器打印对话框,阻塞后续代码执行直到对话框关闭

3.2 对话框操作(alert/confirm/prompt)

方法名称语法用途代码示例注意事项
alert()alert(message)window.alert(message)显示警告对话框,仅包含确定按钮alert('操作成功!');阻塞JavaScript执行直到用户点击确定;现代浏览器可能限制频繁调用;无法自定义样式
confirm()confirm(message)window.confirm(message)显示确认对话框,包含确定和取消按钮if(confirm('确定要删除吗?')) { deleteItem(); }返回true(确定)或false(取消);同样会阻塞代码执行;无法自定义按钮文本
prompt()prompt(message, default)window.prompt(message, default)显示输入对话框,包含文本输入框const userName = prompt('请输入您的姓名:', '匿名用户');返回用户输入的字符串或null(点击取消);第二个参数为输入框默认值;安全性较低,不推荐用于敏感信息输入
对话框通用特性-所有原生对话框的共同特点-1. 阻塞式:暂停脚本执行直到用户响应
2. 模态:阻止用户与页面其他部分交互
3. 样式不可定制:使用操作系统默认样式
4. 可能被浏览器禁用:某些浏览器允许用户禁用这些对话框

3.3 自定义弹窗与模态框

概念/方法名称说明操作细节注意事项
HTML结构创建使用HTML元素构建自定义弹窗创建包含遮罩层(overlay)和弹窗内容(container)的DOM结构:<div id="modal-overlay"><div id="modal-content">...</div></div>遮罩层通常设置position:fixed覆盖整个视口,弹窗内容居中显示
CSS样式设计通过CSS控制弹窗外观和动画遮罩层:background:rgba(0,0,0,0.5); position:fixed; top:0; left:0; width:100%; height:100%
弹窗:position:fixed; top:50%; left:50%; transform:translate(-50%,-50%); background:white; padding:20px
使用transform实现精确居中;考虑响应式设计;添加过渡动画提升用户体验
JavaScript控制逻辑通过JavaScript控制弹窗显示/隐藏function showModal() { document.getElementById('modal-overlay').style.display = 'block'; }
function hideModal() { document.getElementById('modal-overlay').style.display = 'none'; }
绑定事件监听器处理点击遮罩层关闭、ESC键关闭等交互
事件处理处理用户与弹窗的交互document.addEventListener('keydown', function(e) { if(e.key === 'Escape') hideModal(); });
document.getElementById('close-btn').addEventListener('click', hideModal);
考虑键盘可访问性;防止事件冒泡导致意外关闭
焦点管理控制弹窗内的焦点循环弹窗显示时将焦点设置到第一个可聚焦元素;监听Tab键在弹窗内元素间循环提升无障碍访问体验;防止焦点跳到弹窗外的元素
阻止背景滚动弹窗显示时禁止背景页面滚动showModal()中添加:document.body.style.overflow = 'hidden';
hideModal()中恢复:document.body.style.overflow = '';
防止用户滚动背景页面;注意在隐藏弹窗时恢复滚动
动态内容加载根据需要动态填充弹窗内容function showContentModal(content) { document.getElementById('modal-content').innerHTML = content; showModal(); }避免XSS攻击,对动态内容进行适当转义
Promise封装将异步弹窗操作封装为Promisefunction customConfirm(message) { return new Promise((resolve) => { /* 显示确认弹窗,根据用户选择调用resolve(true/false) */ }); }便于使用async/await处理异步操作;提供类似原生confirm的编程体验

四、定时器与异步操作

4.1 setTimeout与setInterval

方法名称语法用途代码示例注意事项
setTimeout()setTimeout(callback, delay, ...args)在指定延迟后执行一次回调函数const timerId = setTimeout(() => { console.log('执行一次'); }, 1000);延迟时间单位为毫秒;实际执行时间可能因浏览器任务队列而延迟;返回定时器ID用于清除
setInterval()setInterval(callback, delay, ...args)按指定间隔重复执行回调函数const intervalId = setInterval(() => { console.log('重复执行'); }, 2000);第一次执行在delay毫秒后,后续每次间隔delay毫秒;可能累积执行(如果回调执行时间超过间隔)
延迟参数delay (number)指定延迟或间隔时间(毫秒)setTimeout(fn, 0); // 尽快执行(加入事件队列末尾)最小延迟:现代浏览器通常限制为4ms(嵌套调用超过5层时);设置为0会使用浏览器最小延迟
参数传递...args (可选)向回调函数传递额外参数setTimeout((name, age) => { console.log(name + ' is ' + age); }, 1000, 'Alice', 25);IE9及以下不支持额外参数,需使用闭包或bind替代
this绑定问题-定时器回调中的this指向问题setTimeout(function() { console.log(this); }, 1000); // this指向window使用箭头函数或bind方法解决:setTimeout(() => { /* this保持外层作用域 */ }, 1000);
嵌套定时器-在定时器回调中创建新定时器setTimeout(function repeat() { /* 任务 */; setTimeout(repeat, delay); }, delay);可避免setInterval的累积执行问题,确保每次执行间隔固定

4.2 定时器清除与管理

方法名称语法用途代码示例注意事项
clearTimeout()clearTimeout(timerId)取消由setTimeout设置的定时器const id = setTimeout(fn, 1000); clearTimeout(id); // 取消执行传入无效ID不会报错;已执行的定时器无法取消
clearInterval()clearInterval(intervalId)取消由setInterval设置的定时器const id = setInterval(fn, 1000); clearInterval(id); // 停止重复执行同clearTimeout,传入无效ID安全;建议在组件卸载/页面隐藏时清理定时器
定时器ID返回值 (number)用于标识和管理定时器const timer1 = setTimeout(fn1, 1000); const timer2 = setTimeout(fn2, 2000);ID是递增的整数,但不应依赖此特性;不同类型的定时器共享ID空间
页面可见性处理document.visibilityState根据页面可见性暂停/恢复定时器document.addEventListener('visibilitychange', () => { if(document.hidden) clearInterval(id); else id = setInterval(fn, 1000); });避免在页面不可见时浪费资源;提升电池续航(移动设备)
组件生命周期清理-在组件销毁时清理定时器class Component { init() { this.timer = setTimeout(...); } destroy() { clearTimeout(this.timer); } }防止内存泄漏和无效操作;React/Vue等框架应在useEffect/cleanup或beforeDestroy中处理
定时器池管理-集中管理多个定时器const timers = []; timers.push(setTimeout(fn1, 1000)); // 清理时:timers.forEach(clearTimeout);适用于需要批量管理定时器的场景;注意及时从池中移除已清除的ID

4.3 requestAnimationFrame

方法/属性名称语法用途代码示例注意事项
requestAnimationFrame()requestAnimationFrame(callback)请求浏览器在下次重绘前执行回调function animate() { /* 动画逻辑 */; requestAnimationFrame(animate); } requestAnimationFrame(animate);回调执行频率通常为60fps(约16.7ms间隔);自动匹配显示器刷新率;返回请求ID用于取消
cancelAnimationFrame()cancelAnimationFrame(requestId)取消已请求的动画帧const id = requestAnimationFrame(animate); cancelAnimationFrame(id);用于停止动画循环;传入无效ID不会报错
回调参数callback(timestamp)回调接收高精度时间戳function animate(time) { console.log('当前时间: ' + time); requestAnimationFrame(animate); }timestamp基于DOMHighResTimeStamp,精度达微秒级;可用于计算精确的动画进度
与setTimeout对比-性能和同步优势不推荐:setTimeout(animate, 16); 推荐:requestAnimationFrame(animate);rAF自动暂停不可见标签页的动画;与浏览器渲染同步,避免布局抖动;更省电
动画循环模式-创建流畅动画的标准模式let startTime = null; function step(currentTime) { if(!startTime) startTime = currentTime; const elapsed = currentTime - startTime; /* 基于elapsed更新动画状态 */; if(elapsed < duration) requestAnimationFrame(step); } requestAnimationFrame(step);使用elapsed时间而非固定增量,确保动画速度一致(不受帧率波动影响)
浏览器兼容性-跨浏览器支持const rAF = window.requestAnimationFrame || window.webkitRequestAnimationFrame || function(cb) { setTimeout(cb, 16); };需考虑各浏览器前缀;提供降级方案(setTimeout模拟)

五、跨窗口通信

5.1 window.open与窗口引用

方法/属性名称语法用途代码示例注意事项
window.open()window.open(url, name, features, replace)打开新窗口并获取其引用const childWin = window.open('child.html', 'child', 'width=400,height=300');返回新窗口的window对象引用;仅当同源时才能访问其DOM和JavaScript
窗口引用属性opener / parent / top / frames访问关联窗口的引用在子窗口中:window.opener.alert('Hello from child!');
在iframe中:parent.postMessage(...);
opener: 打开当前窗口的父窗口
parent: 直接父级窗口(iframe场景)
top: 最顶层窗口
frames: 当前窗口的所有iframe集合
同源策略限制-跨域窗口访问限制try { childWin.document.title = 'New Title'; } catch(e) { console.log('跨域访问被阻止'); }只有同协议、同域名、同端口的窗口才能互相访问DOM和JavaScript;否则抛出SecurityError
窗口状态检测closed 属性检测窗口是否已关闭if(!childWin.closed) { childWin.focus(); }closed属性为只读布尔值;可用于清理已关闭窗口的引用
窗口方法调用-调用关联窗口的方法父窗口调用子窗口方法:childWin.customFunction();
子窗口调用父窗口方法:window.opener.parentFunction();
仅限同源窗口;可传递简单数据或调用预定义函数
窗口名称参数name 参数指定窗口名称或targetwindow.open('page.html', 'myWindow'); // 重用已存在的名为'myWindow'的窗口特殊值:_blank(新窗口)、_self(当前窗口)、_parent(父框架)、_top(顶级框架)

5.2 postMessage跨域通信

方法/属性名称语法用途代码示例注意事项
postMessage()targetWindow.postMessage(message, targetOrigin, [transfer])安全地向其他窗口发送消息childWin.postMessage({action: 'update', data: 'hello'}, 'https://example.com');message: 可序列化的任意数据(对象、数组等)
targetOrigin: 接收方源(协议+域名+端口),*表示任意源(不安全)
transfer: 可转让的对象(如Web Workers)
message事件window.addEventListener('message', handler)接收来自其他窗口的消息window.addEventListener('message', (event) => { if(event.origin !== 'https://trusted.com') return; console.log(event.data); });事件对象包含:data(消息内容)、origin(发送方源)、source(发送方窗口引用)
源验证event.origin验证消息来源的安全性if(event.origin !== expectedOrigin) { console.warn('Unexpected message source'); return; }必须验证origin以防止XSS攻击;避免使用*作为targetOrigin
窗口引用使用event.source获取发送方窗口引用event.source.postMessage('ACK', event.origin); // 回复消息可用于双向通信;仅当同源时才能访问source的其他属性
数据序列化-消息数据的传输机制postMessage({key: 'value'}); // 自动序列化/反序列化使用结构化克隆算法,支持大多数数据类型;不支持函数、Symbol等
错误处理-处理通信异常try { targetWin.postMessage(data, origin); } catch(e) { console.error('PostMessage failed:', e); }当目标窗口不存在或已关闭时可能抛出异常;建议包装在try-catch中

5.3 iframe通信机制

方法/属性名称语法用途代码示例注意事项
iframe元素引用document.getElementById('myFrame').contentWindow获取iframe的window引用const iframeWin = document.getElementById('myFrame').contentWindow; iframeWin.postMessage(...);仅当同源时可直接访问contentWindow的属性和方法
parent属性window.parent在iframe中访问父窗口window.parent.document.getElementById('status').innerText = 'Loaded';同源iframe可直接访问父窗口DOM;跨域时只能使用postMessage
contentDocumentiframe.contentDocument获取iframe的document对象const doc = document.getElementById('myFrame').contentDocument; doc.body.style.backgroundColor = 'red';仅限同源iframe;等价于iframe.contentWindow.document
sandbox属性<iframe sandbox="allow-scripts allow-same-origin">限制iframe的权限<iframe src="untrusted.html" sandbox="allow-scripts"></iframe>默认禁用所有功能;需显式启用所需权限;allow-same-origin允许同源但会禁用allow-scripts(除非同时指定)
postMessage with iframe-iframe与父页面跨域通信父页面:iframe.contentWindow.postMessage(data, '*');
iframe内:window.parent.postMessage(response, '*');
跨域iframe通信的标准方式;必须验证消息来源(origin)
动态创建iframedocument.createElement('iframe')动态加载iframe内容const iframe = document.createElement('iframe'); iframe.src = 'https://other-domain.com'; document.body.appendChild(iframe);可用于按需加载内容;注意跨域限制和安全策略
加载事件监听iframe.onload监听iframe加载完成iframe.onload = function() { console.log('iframe loaded'); };仅在同源或CORS配置正确时可靠触发;跨域iframe可能因安全策略不触发

六、设备与环境检测

6.1 用户代理检测

方法/属性名称语法用途代码示例注意事项
navigator.userAgentnavigator.userAgent获取完整的用户代理字符串const ua = navigator.userAgent; console.log(ua);字符串包含浏览器、操作系统、设备等信息;但可被轻易伪造,不推荐作为唯一检测依据
navigator.platformnavigator.platform获取操作系统平台信息console.log(navigator.platform); // 如 "Win32", "MacIntel", "Linux x86_64"现代浏览器出于隐私考虑可能返回通用值(如总是返回”Win32”)
浏览器检测正则/pattern/.test(userAgent)通过正则表达式解析UA字符串const isChrome = /Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor);需注意浏览器内核兼容性(如Edge基于Chromium后也包含Chrome标识)
移动设备检测-检测是否为移动设备const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);部分平板UA可能与桌面相同;考虑使用触摸事件支持作为辅助判断
引擎检测-检测浏览器渲染引擎const isWebKit = /WebKit/.test(navigator.userAgent); const isGecko = /Gecko/.test(navigator.userAgent) && !/WebKit/.test(navigator.userAgent);现代浏览器多基于Blink(Chromium)或WebKit(Safari),Gecko(Firefox)较少
特性检测替代-推荐使用特性检测而非UA检测if('serviceWorker' in navigator) { /* 支持Service Worker */ }特性检测更可靠:直接检测API是否存在,不受UA字符串变化影响
navigator.vendornavigator.vendor获取浏览器供应商信息console.log(navigator.vendor); // 如 "Google Inc.", "Apple Computer, Inc."可辅助区分同内核的不同浏览器(如Chrome vs Edge)

6.2 屏幕与视口检测

方法/属性名称语法用途代码示例注意事项
screen.width / screen.heightscreen.width / screen.height获取物理屏幕总宽度和高度(像素)console.log('屏幕: ' + screen.width + 'x' + screen.height);返回设备物理分辨率,不受页面缩放影响
screen.availWidth / screen.availHeightscreen.availWidth / screen.availHeight获取可用屏幕尺寸(排除任务栏等系统UI)console.log('可用区域: ' + screen.availWidth + 'x' + screen.availHeight);更准确反映应用可使用的空间
window.innerWidth / innerHeightwindow.innerWidth / window.innerHeight获取浏览器视口(viewport)尺寸console.log('视口: ' + window.innerWidth + 'x' + window.innerHeight);包含滚动条;随窗口大小变化而变化;媒体查询基于此值
document.documentElement.clientWidth / clientHeightdocument.documentElement.clientWidth / document.documentElement.clientHeight获取不包含滚动条的视口尺寸console.log('无滚动条视口: ' + document.documentElement.clientWidth + 'x' + document.documentElement.clientHeight);常用于精确布局计算;IE9+支持
window.devicePixelRatiowindow.devicePixelRatio获取设备像素比(物理像素/逻辑像素)console.log('DPR: ' + window.devicePixelRatio); // 如 1, 1.5, 2, 3高DPR设备(如Retina屏)需要更高分辨率资源;可用于响应式图像处理
matchMedia()window.matchMedia(mediaQueryString)检测CSS媒体查询条件const mediaQuery = window.matchMedia('(max-width: 768px)'); console.log(mediaQuery.matches);返回MediaQueryList对象;可监听变化:mediaQuery.addEventListener('change', handler)
orientation APIscreen.orientation.type获取屏幕方向console.log(screen.orientation.type); // "portrait-primary", "landscape-secondary"等需要HTTPS;部分旧浏览器使用window.orientation(已废弃)
视口缩放检测-检测页面缩放级别const zoom = window.outerWidth / window.innerWidth; // 近似计算精确检测较困难;不同浏览器实现差异大;建议使用CSS transform替代缩放

6.3 网络状态检测

方法/属性名称语法用途代码示例注意事项
navigator.onLinenavigator.onLine检测设备是否连接到网络console.log('在线状态: ' + navigator.onLine); // true/false仅表示设备是否连接到网络(如WiFi/移动数据),不保证实际互联网可达性
online/offline事件window.addEventListener('online', handler) / window.addEventListener('offline', handler)监听网络连接状态变化window.addEventListener('offline', () => { showOfflineMessage(); });当系统网络状态改变时触发;可配合onLine属性使用
Network Information APInavigator.connection获取网络连接详细信息if('connection' in navigator) { console.log('有效类型: ' + navigator.connection.effectiveType); }返回NetworkInformation对象;包含effectiveType(2g/3g/4g/slow-2g)、downlink、rtt等属性
effectiveType属性navigator.connection.effectiveType获取有效网络类型可能值: 'slow-2g', '2g', '3g', '4g'基于实际测量而非用户设置;可用于调整资源加载策略
downlink属性navigator.connection.downlink获取下行带宽估算(Mbps)console.log('下行带宽: ' + navigator.connection.downlink + ' Mbps');仅在安全上下文(HTTPS)中可用;值会动态更新
saveData属性navigator.connection.saveData检测用户是否启用数据节省模式if(navigator.connection.saveData) { loadLowQualityAssets(); }用户可在系统设置中启用;网站应提供轻量级体验
实际连通性检测fetch() / XMLHttpRequest检测实际互联网连接fetch('/ping').then(() => console.log('服务器可达')).catch(() => console.log('连接失败'));navigator.onLine为true时仍可能无法访问特定服务;关键应用应进行实际请求测试
Beacon APInavigator.sendBeacon(url, data)在离线或页面卸载时发送数据window.addEventListener('beforeunload', () => { navigator.sendBeacon('/analytics', data); });即使网络不稳定也能可靠发送;适用于分析和日志数据

七、存储与会话管理

7.1 sessionStorage操作

方法/属性名称语法用途代码示例注意事项
sessionStorage.setItem()sessionStorage.setItem(key, value)存储字符串值到sessionStoragesessionStorage.setItem('username', 'Alice');key和value都必须是字符串;对象需先JSON.stringify()
sessionStorage.getItem()sessionStorage.getItem(key)从sessionStorage获取指定键的值const username = sessionStorage.getItem('username');返回字符串或null(键不存在时);对象需JSON.parse()还原
sessionStorage.removeItem()sessionStorage.removeItem(key)从sessionStorage删除指定键值对sessionStorage.removeItem('username');删除不存在的键不会报错
sessionStorage.clear()sessionStorage.clear()清空当前域下所有sessionStorage数据sessionStorage.clear();仅清除当前源(origin)的数据,不影响其他域
sessionStorage.key()sessionStorage.key(index)获取指定索引位置的键名for(let i=0; i<sessionStorage.length; i++) { console.log(sessionStorage.key(i)); }索引从0开始;length属性返回存储项数量
sessionStorage.lengthsessionStorage.length获取sessionStorage中存储项的数量console.log('存储了 ' + sessionStorage.length + ' 项');只读属性;每次setItem/removeItem后自动更新
生命周期特性-sessionStorage的生命周期规则用户关闭标签页或窗口后数据自动清除数据仅在当前会话期间有效;同一标签页刷新后仍然存在;不同标签页即使同源也互不共享
存储限制-sessionStorage的容量限制通常为5-10MB,具体取决于浏览器超出限制会抛出QuotaExceededError;不同浏览器实现可能不同
事件监听window.addEventListener('storage', handler)监听其他页面对storage的修改window.addEventListener('storage', (e) => { if(e.storageArea === sessionStorage) { console.log(e.key, e.newValue); } });仅在其他页面修改时触发;当前页面的修改不会触发事件

7.2 localStorage操作

方法/属性名称语法用途代码示例注意事项
localStorage.setItem()localStorage.setItem(key, value)存储字符串值到localStoragelocalStorage.setItem('theme', 'dark');同sessionStorage,只接受字符串;持久化存储
localStorage.getItem()localStorage.getItem(key)从localStorage获取指定键的值const theme = localStorage.getItem('theme');返回字符串或null;长期保存,除非手动清除
localStorage.removeItem()localStorage.removeItem(key)从localStorage删除指定键值对localStorage.removeItem('theme');永久删除,不受页面刷新影响
localStorage.clear()localStorage.clear()清空当前域下所有localStorage数据localStorage.clear();彻底清除,用户需重新设置偏好
localStorage.key()localStorage.key(index)获取指定索引位置的键名for(let i=0; i<localStorage.length; i++) { console.log(localStorage.key(i)); }遍历所有存储项的方式之一
localStorage.lengthlocalStorage.length获取localStorage中存储项的数量console.log('本地存储了 ' + localStorage.length + ' 项');只读属性;反映当前存储项总数
持久性特性-localStorage的持久性规则数据永久保存,直到用户手动清除或程序删除即使关闭浏览器、重启设备后仍然存在;不受会话结束影响
存储限制-localStorage的容量限制通常为5-10MB,部分浏览器可达更高同sessionStorage,超出限制抛出QuotaExceededError
事件监听window.addEventListener('storage', handler)监听其他页面对localStorage的修改window.addEventListener('storage', (e) => { if(e.storageArea === localStorage) { applyTheme(e.newValue); } });跨标签页同步状态的有效方式;当前页面修改不触发
私有模式限制-浏览器隐私模式下的行为在无痕/隐私模式下,localStorage可能被禁用或临时存储尝试使用前应进行功能检测:try { localStorage.setItem('test', 'test'); } catch(e) { /* 处理异常 */ }

7.3 Cookie操作(document.cookie)

方法/属性名称语法用途代码示例注意事项
document.cookie (读取)document.cookie获取当前可访问的Cookie字符串console.log(document.cookie); // "name=Alice; age=25"仅返回未标记HttpOnly的Cookie;格式为分号分隔的键值对
document.cookie (写入)document.cookie = "key=value; attributes"设置Cookie及其属性document.cookie = "username=Alice; expires=Fri, 31 Dec 2026 23:59:59 GMT; path=/";写入时需指定完整字符串;仅修改指定的键,不影响其他Cookie
expires属性expires=date设置Cookie过期时间document.cookie = "session=abc123; expires=" + new Date(Date.now() + 3600000).toUTCString();过期后自动删除;不设置则为会话Cookie(关闭浏览器后删除)
max-age属性max-age=seconds设置Cookie最大存活时间(秒)document.cookie = "pref=dark; max-age=86400"; // 24小时优先级高于expires;现代浏览器推荐使用
path属性path=path设置Cookie的作用路径document.cookie = "auth=token; path=/api";仅当请求URL路径匹配时才发送Cookie;默认为当前文档路径
domain属性domain=domain设置Cookie的作用域名document.cookie = "user=id123; domain=.example.com";可设置为父域名以在子域名间共享;不能设置为其他顶级域名
secure属性secure仅通过HTTPS传输Cookiedocument.cookie = "secureData=secret; secure";HTTP页面无法设置带secure属性的Cookie;提升安全性
httpOnly属性HttpOnly禁止JavaScript访问Cookie只能通过服务器Set-Cookie头设置:Set-Cookie: sessionId=abc; HttpOnlydocument.cookie无法读取或修改HttpOnly Cookie;防御XSS攻击
sameSite属性SameSite=Strict/Lax/None控制跨站请求时Cookie的发送document.cookie = "csrf=token; SameSite=Lax";Strict: 完全禁止跨站
Lax: 允许安全HTTP方法(GET等)跨站
None: 始终发送(需配合secure)
编码处理encodeURIComponent() / decodeURIComponent()处理Cookie值中的特殊字符document.cookie = "info=" + encodeURIComponent("Hello World!");
const info = decodeURIComponent(document.cookie.split('; ').find(row => row.startsWith('info='))?.split('=')[1]);
Cookie值不能包含分号、逗号、空格等特殊字符
存储限制-Cookie的容量和数量限制单个Cookie通常≤4KB;每个域名通常≤50个Cookie超出限制可能导致旧Cookie被丢弃;影响HTTP请求大小(每次都会发送)
安全最佳实践-Cookie安全使用建议敏感数据使用HttpOnly+Secure+SameSite=Strict避免在Cookie中存储敏感信息;优先使用localStorage/sessionStorage存储客户端数据

八、高级BOM功能

8.1 Web Workers

方法/属性名称语法用途代码示例注意事项
Worker构造函数new Worker(scriptURL, options)创建Web Worker实例const worker = new Worker('worker.js');scriptURL必须同源;options可包含type(‘classic’或’module’)
postMessage()worker.postMessage(message, transferList)向Worker发送消息worker.postMessage({data: [1,2,3]}, [arrayBuffer]);message可为任意可序列化数据;transferList用于转移所有权(如ArrayBuffer)提升性能
onmessage事件worker.onmessage = handlerworker.addEventListener('message', handler)接收Worker发回的消息worker.onmessage = (e) => { console.log('Result:', e.data); };事件对象e.data包含Worker返回的数据
terminate()worker.terminate()立即终止Workerworker.terminate(); // 释放资源强制终止,不会触发Worker的onclose事件;应优先使用worker.postMessage(‘close’)让Worker自行关闭
importScripts()importScripts(url1, url2, ...)在Worker中加载外部脚本在worker.js中:importScripts('lodash.js', 'utils.js');只能在Worker上下文中使用;同步加载,阻塞执行
self引用selfWorker内部的全局对象引用在worker.js中:self.onmessage = (e) => { /* 处理消息 */ };等价于Worker中的window;也可直接使用onmessage全局变量
错误处理worker.onerror / self.onerror捕获Worker错误worker.onerror = (e) => { console.error('Worker error:', e.message); };包含message、filename、lineno等错误信息;未处理的错误会终止Worker
SharedWorkernew SharedWorker(scriptURL)创建可在多个浏览上下文共享的Workerconst sharedWorker = new SharedWorker('shared-worker.js'); sharedWorker.port.start();通过port属性通信;适用于多标签页共享状态场景
存储限制-Worker中的存储访问Worker中无法访问localStorage/sessionStorage可使用IndexedDB;不能访问DOM、window对象、document等主线程API
模块化Workernew Worker('module-worker.js', { type: 'module' })使用ES模块语法的Workermodule-worker.js使用import/export需要显式指定{type: ‘module’};支持现代模块语法

8.2 Service Workers

方法/属性名称语法用途代码示例注意事项
register()navigator.serviceWorker.register(scriptURL, options)注册Service Workernavigator.serviceWorker.register('/sw.js').then(reg => console.log('SW registered'));必须在HTTPS环境下(localhost除外);scope默认为scriptURL所在目录
scope选项{ scope: './' }设置Service Worker控制范围navigator.serviceWorker.register('/sw.js', { scope: '/app/' });scope必须是scriptURL的子路径;控制该路径下所有请求
install事件self.addEventListener('install', event)监听安装事件self.addEventListener('install', (e) => { e.waitUntil(caches.open('v1').then(cache => cache.addAll(['/']))); });waitUntil()确保安装完成前不视为installed;用于缓存静态资源
activate事件self.addEventListener('activate', event)监听激活事件self.addEventListener('activate', (e) => { e.waitUntil(clients.claim()); });通常用于清理旧缓存;clients.claim()使SW立即控制当前页面
fetch事件self.addEventListener('fetch', event)拦截网络请求self.addEventListener('fetch', (e) => { e.respondWith(caches.match(e.request).then(r => r || fetch(e.request))); });respondWith()必须同步调用;可实现离线缓存策略
skipWaiting()self.skipWaiting()跳过等待状态立即激活self.addEventListener('install', (e) => { self.skipWaiting(); });使新版本SW立即接管页面,无需等待所有客户端关闭
clients.claim()clients.claim()立即控制未受控的客户端self.addEventListener('activate', (e) => { e.waitUntil(clients.claim()); });使当前打开的页面立即受新SW控制
缓存APIcaches.open(name) → Cache操作缓存存储caches.open('my-cache').then(cache => cache.put(request, response));持久化存储;与localStorage独立;可通过Cache Storage API管理
更新机制navigator.serviceWorker.getRegistration()检测和更新SWnavigator.serviceWorker.getRegistration().then(reg => reg.update());浏览器每24小时自动检查更新;也可手动触发update()
消息通信navigator.serviceWorker.controller.postMessage(data)与激活的SW通信if(navigator.serviceWorker.controller) { navigator.serviceWorker.controller.postMessage({action: 'sync'}); }SW通过self.onmessage接收;可用于推送数据到SW
生命周期状态registration.active / waiting / installing获取SW注册状态console.log('Active SW:', registration.active);installing: 正在安装
waiting: 已安装但未激活
active: 已激活并控制页面

8.3 Geolocation(地理位置)

方法/属性名称语法用途代码示例注意事项
getCurrentPosition()navigator.geolocation.getCurrentPosition(successCallback, errorCallback, options)获取当前地理位置navigator.geolocation.getCurrentPosition(pos => { console.log(pos.coords.latitude, pos.coords.longitude); });首次调用会触发用户权限请求;successCallback接收Position对象
watchPosition()navigator.geolocation.watchPosition(successCallback, errorCallback, options)持续监听位置变化const watchId = navigator.geolocation.watchPosition(updateMap);返回watch ID;位置变化或设备移动时触发回调;比getCurrentPosition更耗电
clearWatch()navigator.geolocation.clearWatch(watchId)停止位置监听navigator.geolocation.clearWatch(watchId);释放资源;停止GPS/网络定位
Position对象position.coords包含地理坐标信息coords包含:latitude(纬度)、longitude(经度)、accuracy(精度/米)、altitude(海拔/米)、altitudeAccuracy(海拔精度)、heading(行进方向/度)、speed(速度/米/秒)altitude、heading、speed可能为null(设备不支持或无法获取)
PositionOptions{ enableHighAccuracy, timeout, maximumAge }定位选项配置navigator.geolocation.getCurrentPosition(success, error, { enableHighAccuracy: true, timeout: 10000, maximumAge: 60000 });enableHighAccuracy: 使用GPS(更精确但耗电)
timeout: 获取位置的超时时间(毫秒)
maximumAge: 可接受的缓存位置最大年龄(毫秒)
错误处理errorCallback(error)处理定位错误const errorHandler = (err) => { switch(err.code) { case 1: console.log('用户拒绝授权'); break; case 2: console.log('位置不可用'); break; case 3: console.log('超时'); break; } };error.code: 1=PERMISSION_DENIED, 2=POSITION_UNAVAILABLE, 3=TIMEOUT
error.message: 详细错误信息
权限状态检测Permissions API检测地理位置权限状态navigator.permissions.query({name:'geolocation'}).then(result => { console.log(result.state); // 'granted', 'denied', 'prompt' });需要HTTPS;可避免不必要的权限弹窗
安全上下文要求-Geolocation的安全要求仅在安全上下文(HTTPS或localhost)中可用HTTP页面(非localhost)无法使用Geolocation API;现代浏览器强制要求
电池优化影响-移动设备省电模式的影响省电模式可能降低定位频率或禁用后台定位Android/iOS系统级优化可能影响watchPosition的准确性;建议提供手动刷新选项
模拟位置检测-检测开发者工具模拟位置无标准API;可通过速度/精度异常间接判断某些应用(如打车、签到)需防范模拟位置;但无可靠检测方法