【Web APIs-Day5】BOM与本地存储
📺 对应视频:P127-P137 | 🎯 核心目标:掌握BOM对象体系、事件循环机制、location/navigator对象与本地存储API
一、BOM 概述
1.1 BOM 是什么?
BOM(Browser Object Model,浏览器对象模型)提供了与浏览器窗口交互的接口。
window(顶层对象,全局作用域)
├── document → DOM 操作
├── location → URL 信息与跳转
├── navigator → 浏览器/设备信息
├── history → 浏览器历史记录
├── screen → 屏幕信息
└── localStorage / sessionStorage → 本地存储
💡 注意:
window是全局对象,所有全局变量和函数都是window的属性。alert()、setTimeout()实际上是window.alert()、window.setTimeout()。
二、事件循环(Event Loop)
2.1 JS 为什么是单线程?
JS 设计之初是为了操作 DOM,多线程操作同一个 DOM 会产生竞争问题,所以 JS 是单线程的。
2.2 同步与异步
// 同步代码:按顺序执行,后面的必须等前面的完成
console.log('1')
console.log('2')
console.log('3')
// 输出:1 2 3
// 异步代码:不阻塞,放到"任务队列"等待
console.log('1')
setTimeout(() => {
console.log('2') // 异步,即使延迟为0也在最后执行
}, 0)
console.log('3')
// 输出:1 3 2
2.3 事件循环机制
执行栈(Call Stack)← 同步代码在这里执行
↑
├── 宏任务队列(Macro Task Queue)
│ setTimeout / setInterval / I/O / UI渲染
│
└── 微任务队列(Micro Task Queue)← 优先于宏任务!
Promise.then / MutationObserver / queueMicrotask
执行顺序:
- 执行同步代码(Call Stack)
- 清空全部微任务队列
- 取出一个宏任务执行
- 再次清空全部微任务队列
- 重复 3-4
console.log('1') // 同步
setTimeout(() => {
console.log('2') // 宏任务
}, 0)
Promise.resolve().then(() => {
console.log('3') // 微任务
})
console.log('4') // 同步
// 输出顺序:1 4 3 2
// 同步先执行,微任务优先于宏任务
三、location 对象
3.1 URL 解析
URL 结构:
https://www.example.com:8080/path/page.html?id=1&name=张三#section2
location.href → 'https://www.example.com:8080/path/page.html?id=1&name=张三#section2'
location.protocol → 'https:'
location.host → 'www.example.com:8080'
location.hostname → 'www.example.com'
location.port → '8080'
location.pathname → '/path/page.html'
location.search → '?id=1&name=张三'(查询字符串)
location.hash → '#section2'(锚点)
location.origin → 'https://www.example.com:8080'
3.2 页面跳转
// 跳转(会留下历史记录,可以回退)
location.href = 'https://juejin.cn'
location.assign('https://juejin.cn') // 同上
// 替换(不留历史记录,无法回退)
location.replace('https://juejin.cn')
// 重新加载
location.reload() // 普通刷新
location.reload(true) // 强制刷新(忽略缓存)
3.3 解析查询参数
// 解析 ?id=1&name=张三
const params = new URLSearchParams(location.search)
params.get('id') // '1'
params.get('name') // '张三'
params.has('id') // true
params.delete('id')
// 遍历所有参数
for (const [key, value] of params) {
console.log(`${key}: ${value}`)
}
// 将参数传给下一页
const url = new URL('https://example.com/detail')
url.searchParams.set('id', 123)
url.searchParams.set('from', 'home')
location.href = url.toString()
// → https://example.com/detail?id=123&from=home
四、navigator 对象
// 浏览器信息
navigator.userAgent // 用户代理字符串(识别浏览器/OS)
navigator.language // 浏览器语言,如 'zh-CN'
navigator.onLine // 是否联网(true/false)
navigator.platform // 操作系统平台
navigator.cookieEnabled // 是否启用 Cookie
// 判断移动端
function isMobile() {
return /Android|iPhone|iPad|iPod|Mobile/i.test(navigator.userAgent)
}
// 根据设备跳转不同页面
if (isMobile()) {
location.href = '/m/index.html' // 移动版
} else {
location.href = '/pc/index.html' // PC版
}
// 获取地理位置(需要用户授权)
navigator.geolocation.getCurrentPosition(
position => {
const { latitude, longitude } = position.coords
console.log(`纬度:${latitude},经度:${longitude}`)
},
error => {
console.log('获取位置失败:', error.message)
}
)
五、history 对象
history.back() // 后退(等同于浏览器返回按钮)
history.forward() // 前进
history.go(-1) // 后退1步
history.go(1) // 前进1步
history.go(0) // 刷新
// 操作历史记录(SPA 路由的基础)
history.pushState({ page: 1 }, '', '/page1') // 添加历史记录,URL变化但不刷新
history.replaceState({ page: 2 }, '', '/page2') // 替换当前历史记录
// 监听前进/后退
window.addEventListener('popstate', e => {
console.log('历史变化:', e.state)
})
六、本地存储
6.1 localStorage(持久化存储)
// 特点:
// - 容量约 5MB
// - 不会过期,除非手动清除
// - 同域名下共享(跨 tab 页可访问)
// - 只能存字符串!
// 存储
localStorage.setItem('username', '张三')
localStorage.setItem('age', 18) // 数字自动转字符串
// 读取
localStorage.getItem('username') // '张三'
localStorage.getItem('age') // '18'(字符串!)
// 删除
localStorage.removeItem('username')
// 清空所有
localStorage.clear()
// 存储对象(必须序列化)
const user = { name: '张三', age: 18 }
localStorage.setItem('user', JSON.stringify(user)) // 存
const savedUser = JSON.parse(localStorage.getItem('user')) // 取
// 封装工具函数
const storage = {
set(key, value) {
localStorage.setItem(key, JSON.stringify(value))
},
get(key) {
const val = localStorage.getItem(key)
return val ? JSON.parse(val) : null
},
remove(key) {
localStorage.removeItem(key)
}
}
6.2 sessionStorage(会话存储)
// 特点:
// - 容量约 5MB
// - 关闭 tab 页即清除
// - 仅限当前 tab(不跨标签页)
// - 也只能存字符串
// API 与 localStorage 完全相同
sessionStorage.setItem('token', 'abc123')
sessionStorage.getItem('token')
sessionStorage.removeItem('token')
sessionStorage.clear()
6.3 localStorage vs sessionStorage vs Cookie
| 特性 | localStorage | sessionStorage | Cookie |
|---|---|---|---|
| 容量 | ~5MB | ~5MB | ~4KB |
| 过期时间 | 永久 | 关闭标签清除 | 可设置 |
| 随请求发送 | ❌ | ❌ | ✅(自动) |
| 跨 tab | ✅ | ❌ | ✅ |
| JS 可访问 | ✅ | ✅ | 可设置限制 |
七、综合案例
案例:记住用户设置
// 读取用户保存的主题
const savedTheme = localStorage.getItem('theme') || 'light'
document.body.className = savedTheme
// 切换主题并保存
document.querySelector('.theme-toggle').addEventListener('click', () => {
const current = document.body.className
const newTheme = current === 'light' ? 'dark' : 'light'
document.body.className = newTheme
localStorage.setItem('theme', newTheme)
})
案例:购物车持久化
// 读取购物车
function getCart() {
return JSON.parse(localStorage.getItem('cart')) || []
}
// 添加商品
function addToCart(product) {
const cart = getCart()
const existing = cart.find(item => item.id === product.id)
if (existing) {
existing.quantity++
} else {
cart.push({ ...product, quantity: 1 })
}
localStorage.setItem('cart', JSON.stringify(cart))
}
八、知识图谱
BOM 与本地存储
├── BOM 对象体系
│ └── window 顶层:location / navigator / history / screen
├── 事件循环
│ ├── 同步代码(调用栈)
│ ├── 微任务(Promise.then)← 优先
│ └── 宏任务(setTimeout)← 后执行
├── location
│ ├── href / pathname / search / hash
│ ├── assign / replace(跳转)
│ └── URLSearchParams(解析查询参数)
├── navigator
│ ├── userAgent(识别设备/浏览器)
│ └── geolocation(获取位置)
├── history
│ ├── back / forward / go
│ └── pushState / replaceState(SPA路由)
└── 本地存储
├── localStorage(持久):setItem/getItem/removeItem
├── sessionStorage(会话):同上
└── 注意:只能存字符串,对象需 JSON 序列化
九、高频面试题
Q1:宏任务和微任务的区别?哪些属于微任务?
微任务:
Promise.then、MutationObserver、queueMicrotask;宏任务:setTimeout、setInterval、requestAnimationFrame、UI 渲染。同步代码完成后,先清空全部微任务,再取一个宏任务执行,如此循环。
Q2:localStorage 和 sessionStorage 的区别?
两者 API 完全相同,区别在于:
localStorage数据永久保存,关闭浏览器后仍然存在,且多个 tab 共享;sessionStorage在关闭 tab 页后清除,且不跨 tab。
Q3:如何跨页面传递数据?
① URL 参数(
?id=1):小量数据;②localStorage:大量数据持久化;③sessionStorage:临时数据;④BroadcastChannel:实时跨 tab 通信;⑤ 后端存储(推荐重要数据)。
⬅️ 上一篇:Web APIs Day4 - 节点操作 ➡️ 下一篇:Web APIs Day6&7 - 正则与综合实战