03BOM 浏览器环境
DOM 管「页面里的东西」,BOM(Browser Object Model)管「浏览器本身」: 地址栏、历史记录、窗口尺寸、定时器、存储。 做单页应用、多页跳转、记住用户偏好,都绕不开它。
一、BOM 地图:挂在 window 上
全局对象。变量、定时器、弹窗、尺寸都挂这里。浏览器里 window === globalThis。
地址栏:URL 解析、跳转、刷新、hash 查询参数。
前进 / 后退 / 替换当前记录(SPA 路由基础)。
UA、语言、在线状态、剪贴板、地理信息(注意隐私)。
屏幕与视口尺寸。响应式检测、弹层定位要用。
键值存储(08 章学过),BOM 侧的「记忆」。
二、location:读 URL 与跳转
| 属性 / 方法 | 含义 | 示例 |
|---|---|---|
location.href | 完整 URL(可赋值跳转) | location.href = '/home' |
location.pathname | 路径 | /user/1 |
location.search | 查询串(含 ?) | ?id=1&q=js |
location.hash | 锚点(含 #) | #sec-2 |
location.reload() | 刷新 | location.reload(true) |
location.assign(url) | 跳转(可后退) | — |
location.replace(url) | 替换(不可后退) | 登录后跳首页 |
点按钮查看 location
三、history:前进后退与替换
pushState 会多一条历史记录(可后退);
replaceState 换掉当前这条(不可后退)。
登录后跳转、分页筛选,常用 replaceState,避免用户后退又回到登录页。四、窗口尺寸与弹层定位
点按钮
matchMedia,
不要用 UA 字符串硬解析——平板、折叠屏、桌面缩放都会骗过 UA。五、定时器家族(和事件循环连起来)
| API | 用途 | 注意 |
|---|---|---|
setTimeout | 延迟一次 | 嵌套有 4ms 节流;返回 id 用于 clear |
setInterval | 周期重复 | 容易漏 clear 造成泄漏;回调积压 |
requestAnimationFrame | 帧同步动画 | 标签隐藏时暂停,省电 |
requestIdleCallback | 空闲时做次要任务 | 兼容性一般,可 polyfill |
六、常见问题 · 自问自答
为什么刷新页面后表单内容 / 展开状态丢了?
内存变量不会跨刷新。把需要记住的状态写进
localStorage(长期)或 sessionStorage(当前标签);
也可以把状态编码进 location.hash / query,刷新后还能恢复。
location.assign 和 replace 有什么差别?
assign 像点了个链接——历史里多一条,用户能「后退」回来;
replace 把当前记录换掉,后退会跳过这一页。
登录成功跳首页用 replace,免得后退又回到登录表单。
setInterval 为什么越跑越卡?
回调执行时间若大于间隔,会排队积压。
改用 setTimeout 递归(上次做完再排下次),或动画交给
requestAnimationFrame。组件销毁记得 clearInterval。
怎么判断用户手机还是电脑?
布局相关:用 matchMedia('(pointer: coarse)') /
matchMedia('(max-width: 768px)')。
只有做「下载 App 提示」这类产品逻辑才看 navigator.userAgent,
且要做好兜底。
为什么我的 history.pushState 改了 URL 页面却没变?
这是预期行为:pushState只改地址和历史栈,不加载新文档。
路由变化要自己监听 popstate 并渲染。真正刷新要用 location.href。
七、本章小结
- BOM 挂在
window上:location/history/navigator/ 尺寸 / 定时器。 - 读查询串用
URLSearchParams;跳转分清assign与replace。 - SPA 靠
pushState+popstate,不刷新换页。 - 响应式判断用
matchMedia;定时器用完必clear。 - 要跨刷新的状态 →
localStorage或 URL。
?id=1 读出 id 并显示在标题;
② 做一个「记住侧边栏折叠状态」(localStorage);
③ 用 pushState/replaceState 演示后退行为差异。