Article
一、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/innerHeight | window.innerWidth / window.innerHeight | 获取视口(viewport)宽度和高度 | console.log(window.innerWidth); | 包含滚动条在内的视口尺寸,不包含浏览器UI |
| outerWidth/outerHeight | window.outerWidth / window.outerHeight | 获取浏览器窗口外部尺寸 | console.log(window.outerWidth); | 包含浏览器UI(地址栏、工具栏等)的完整窗口尺寸 |
| scrollX/scrollY | window.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操作)
| 方法/属性名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| href | location.href | 获取或设置完整URL | console.log(location.href); location.href = "https://example.com"; | 设置href会触发页面跳转,等同于assign()方法 |
| protocol | location.protocol | 获取URL协议 | console.log(location.protocol); // "https:" | 返回值包含冒号,如”http:”、“https:“ |
| host | location.host | 获取主机名和端口 | console.log(location.host); // "example.com:8080" | 包含端口号(如果有) |
| hostname | location.hostname | 获取主机名 | console.log(location.hostname); // "example.com" | 不包含端口号 |
| port | location.port | 获取端口号 | console.log(location.port); // "8080" | 如果使用默认端口(80/443),可能返回空字符串 |
| pathname | location.pathname | 获取路径部分 | console.log(location.pathname); // "/path/page.html" | 从域名后的第一个斜杠开始 |
| search | location.search | 获取查询字符串 | console.log(location.search); // "?id=123&name=test" | 包含问号,可配合URLSearchParams解析 |
| hash | location.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对象(浏览器信息)
| 方法/属性名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| userAgent | navigator.userAgent | 获取用户代理字符串 | console.log(navigator.userAgent); | 可用于检测浏览器类型,但容易被伪造,不推荐作为唯一检测依据 |
| platform | navigator.platform | 获取操作系统平台 | console.log(navigator.platform); // "Win32"、"MacIntel"等 | 返回值可能不准确,现代浏览器出于隐私考虑可能返回通用值 |
| language | navigator.language | 获取浏览器首选语言 | console.log(navigator.language); // "zh-CN"、"en-US"等 | 返回用户的首选语言设置 |
| languages | navigator.languages | 获取用户偏好的语言列表 | console.log(navigator.languages); // ["zh-CN", "en-US"] | 返回数组,按偏好程度排序 |
| onLine | navigator.onLine | 检测网络连接状态 | console.log(navigator.onLine); // true/false | 只能检测设备是否连接到网络,不能保证实际互联网连接 |
| geolocation | navigator.geolocation | 访问地理位置API | navigator.geolocation.getCurrentPosition(success, error); | 需要用户授权,仅在安全上下文(HTTPS)中可用 |
| cookieEnabled | navigator.cookieEnabled | 检测Cookie是否启用 | console.log(navigator.cookieEnabled); // true/false | 返回布尔值,指示浏览器是否启用了Cookie |
| hardwareConcurrency | navigator.hardwareConcurrency | 获取CPU逻辑处理器数量 | console.log(navigator.hardwareConcurrency); // 4、8等 | 可用于性能优化,但出于隐私考虑可能返回较低值 |
| maxTouchPoints | navigator.maxTouchPoints | 获取设备支持的最大触摸点数 | console.log(navigator.maxTouchPoints); // 0(非触摸设备)、5、10等 | 用于检测设备触摸能力 |
| sendBeacon() | navigator.sendBeacon(url, data) | 在页面卸载时发送数据 | navigator.sendBeacon("/log", analyticsData); | 保证数据可靠发送,即使页面正在关闭 |
2.4 screen对象(屏幕信息)
| 方法/属性名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| width | screen.width | 获取屏幕宽度(像素) | console.log(screen.width); // 1920 | 返回物理屏幕的总宽度,不受缩放影响 |
| height | screen.height | 获取屏幕高度(像素) | console.log(screen.height); // 1080 | 返回物理屏幕的总高度,不受缩放影响 |
| availWidth | screen.availWidth | 获取可用屏幕宽度 | console.log(screen.availWidth); // 1920 | 减去操作系统UI(如任务栏)后的可用宽度 |
| availHeight | screen.availHeight | 获取可用屏幕高度 | console.log(screen.availHeight); // 1040 | 减去操作系统UI后的可用高度 |
| colorDepth | screen.colorDepth | 获取屏幕色深 | console.log(screen.colorDepth); // 24 | 表示每个像素的颜色位数,通常为24或32 |
| pixelDepth | screen.pixelDepth | 获取屏幕像素深度 | console.log(screen.pixelDepth); // 24 | 通常与colorDepth相同 |
| orientation | screen.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对象(浏览历史)
| 方法/属性名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| length | history.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"); | 同样不会触发页面刷新,但替换当前条目而非添加新条目 |
| state | history.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封装 | 将异步弹窗操作封装为Promise | function 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 参数 | 指定窗口名称或target | window.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 |
| contentDocument | iframe.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) |
| 动态创建iframe | document.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.userAgent | navigator.userAgent | 获取完整的用户代理字符串 | const ua = navigator.userAgent; console.log(ua); | 字符串包含浏览器、操作系统、设备等信息;但可被轻易伪造,不推荐作为唯一检测依据 |
| navigator.platform | navigator.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.vendor | navigator.vendor | 获取浏览器供应商信息 | console.log(navigator.vendor); // 如 "Google Inc.", "Apple Computer, Inc." | 可辅助区分同内核的不同浏览器(如Chrome vs Edge) |
6.2 屏幕与视口检测
| 方法/属性名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| screen.width / screen.height | screen.width / screen.height | 获取物理屏幕总宽度和高度(像素) | console.log('屏幕: ' + screen.width + 'x' + screen.height); | 返回设备物理分辨率,不受页面缩放影响 |
| screen.availWidth / screen.availHeight | screen.availWidth / screen.availHeight | 获取可用屏幕尺寸(排除任务栏等系统UI) | console.log('可用区域: ' + screen.availWidth + 'x' + screen.availHeight); | 更准确反映应用可使用的空间 |
| window.innerWidth / innerHeight | window.innerWidth / window.innerHeight | 获取浏览器视口(viewport)尺寸 | console.log('视口: ' + window.innerWidth + 'x' + window.innerHeight); | 包含滚动条;随窗口大小变化而变化;媒体查询基于此值 |
| document.documentElement.clientWidth / clientHeight | document.documentElement.clientWidth / document.documentElement.clientHeight | 获取不包含滚动条的视口尺寸 | console.log('无滚动条视口: ' + document.documentElement.clientWidth + 'x' + document.documentElement.clientHeight); | 常用于精确布局计算;IE9+支持 |
| window.devicePixelRatio | window.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 API | screen.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.onLine | navigator.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 API | navigator.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 API | navigator.sendBeacon(url, data) | 在离线或页面卸载时发送数据 | window.addEventListener('beforeunload', () => { navigator.sendBeacon('/analytics', data); }); | 即使网络不稳定也能可靠发送;适用于分析和日志数据 |
七、存储与会话管理
7.1 sessionStorage操作
| 方法/属性名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| sessionStorage.setItem() | sessionStorage.setItem(key, value) | 存储字符串值到sessionStorage | sessionStorage.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.length | sessionStorage.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) | 存储字符串值到localStorage | localStorage.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.length | localStorage.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传输Cookie | document.cookie = "secureData=secret; secure"; | HTTP页面无法设置带secure属性的Cookie;提升安全性 |
| httpOnly属性 | HttpOnly | 禁止JavaScript访问Cookie | 只能通过服务器Set-Cookie头设置:Set-Cookie: sessionId=abc; HttpOnly | document.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 = handler 或 worker.addEventListener('message', handler) | 接收Worker发回的消息 | worker.onmessage = (e) => { console.log('Result:', e.data); }; | 事件对象e.data包含Worker返回的数据 |
| terminate() | worker.terminate() | 立即终止Worker | worker.terminate(); // 释放资源 | 强制终止,不会触发Worker的onclose事件;应优先使用worker.postMessage(‘close’)让Worker自行关闭 |
| importScripts() | importScripts(url1, url2, ...) | 在Worker中加载外部脚本 | 在worker.js中:importScripts('lodash.js', 'utils.js'); | 只能在Worker上下文中使用;同步加载,阻塞执行 |
| self引用 | self | Worker内部的全局对象引用 | 在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 |
| SharedWorker | new SharedWorker(scriptURL) | 创建可在多个浏览上下文共享的Worker | const sharedWorker = new SharedWorker('shared-worker.js'); sharedWorker.port.start(); | 通过port属性通信;适用于多标签页共享状态场景 |
| 存储限制 | - | Worker中的存储访问 | Worker中无法访问localStorage/sessionStorage | 可使用IndexedDB;不能访问DOM、window对象、document等主线程API |
| 模块化Worker | new Worker('module-worker.js', { type: 'module' }) | 使用ES模块语法的Worker | module-worker.js使用import/export | 需要显式指定{type: ‘module’};支持现代模块语法 |
8.2 Service Workers
| 方法/属性名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| register() | navigator.serviceWorker.register(scriptURL, options) | 注册Service Worker | navigator.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控制 |
| 缓存API | caches.open(name) → Cache | 操作缓存存储 | caches.open('my-cache').then(cache => cache.put(request, response)); | 持久化存储;与localStorage独立;可通过Cache Storage API管理 |
| 更新机制 | navigator.serviceWorker.getRegistration() | 检测和更新SW | navigator.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;可通过速度/精度异常间接判断 | 某些应用(如打车、签到)需防范模拟位置;但无可靠检测方法 |