DOM与BOM
浏览器端编程的核心是 DOM(文档对象模型)和 BOM(浏览器对象模型):DOM 操作页面内容,BOM 操作浏览器窗口。JavaScript 在浏览器里不能直接碰文件系统和网络栈,只能通过这两个模型提供的 API 与页面交互——这是浏览器沙箱的边界。Node.js开发 是服务端运行时,本文聚焦浏览器侧。
DOM 树
DOM 把 HTML 文档解析成一棵对象树,每个标签、文本、属性都是节点,JavaScript 通过节点操作页面。
<!DOCTYPE html>
<html>
<body>
<div id="app">
<p class="title">你好</p>
</div>
</body>
</html>常用节点类型:document(根)、元素节点(标签)、文本节点、属性节点。DOM 操作是 JS 面试高频题,核心是选择器和增删改。
选择元素
| 方法 | 返回 | 示例 |
|---|---|---|
getElementById | 单个元素 | document.getElementById('app') |
querySelector | 单个元素(CSS 选择器) | document.querySelector('.title') |
querySelectorAll | NodeList(类数组) | document.querySelectorAll('p') |
getElementsByClassName | 实时 HTMLCollection | document.getElementsByClassName('title') |
const app = document.getElementById('app');
const title = document.querySelector('.title');
const allP = document.querySelectorAll('p'); // 注意:静态快照
// 遍历 NodeList
allP.forEach(p => console.log(p.textContent));querySelector 优先
querySelector/querySelectorAll 支持完整 CSS 选择器,统一语法,优先使用;getElementsBy* 返回实时集合(DOM 变化自动更新),在循环中删除元素时要小心索引错乱。
修改内容与样式
const el = document.querySelector('.title');
// 文本与 HTML
el.textContent = '新文本'; // 纯文本,安全
el.innerHTML = '<b>加粗</b>'; // 解析 HTML,注意 XSS 风险
// 属性
el.setAttribute('data-id', '42');
el.id = 'newId';
// 样式
el.style.color = 'red';
el.classList.add('active'); // 操作 class 用 classList
el.classList.toggle('active'); // 切换innerHTML 的 XSS 风险
innerHTML 会解析插入的 HTML 字符串。把用户输入直接塞进 innerHTML,恶意脚本会被执行(XSS 攻击)。插入纯文本用 textContent;必须渲染富文本时先转义或使用白名单过滤。
事件模型
事件机制的核心是"捕获 → 目标 → 冒泡"三阶段传播。点击一个嵌套元素,事件先沿捕获路径从根到目标,再沿冒泡路径从目标回根:
// 冒泡:点击子元素会触发父元素监听器
parent.addEventListener('click', () => console.log('父元素'));
child.addEventListener('click', () => console.log('子元素'));
// 点击 child 输出:子元素 → 父元素
// 阻止冒泡
child.addEventListener('click', (e) => {
e.stopPropagation(); // 不再往上冒泡
});
// 阻止默认行为(如表单提交、链接跳转)
e.preventDefault();事件委托
利用冒泡机制,把监听器挂在父元素上统一处理子元素事件——动态添加的子元素无需逐个绑定,性能更好:
document.querySelector('ul').addEventListener('click', (e) => {
if (e.target.tagName === 'LI') {
console.log('点了', e.target.textContent);
}
});BOM 对象
BOM 提供操作浏览器窗口的 API,核心对象是 window(DOM 的 document 也是它的属性):
| 对象/属性 | 用途 |
|---|---|
window.location | 当前 URL 及跳转 |
window.history | 前进/后退历史 |
window.navigator | 浏览器信息(UA、语言) |
window.localStorage / sessionStorage | 本地存储 |
window.screen | 屏幕尺寸 |
setTimeout / setInterval | 定时器(全局函数) |
// location:跳转与信息
window.location.href = 'https://example.com'; // 跳转
console.log(location.search); // ?a=1&b=2
// 存储:localStorage 持久,sessionStorage 关标签页即清
localStorage.setItem('token', 'abc123');
const token = localStorage.getItem('token');
localStorage.removeItem('token');
// 定时器
const id = setTimeout(() => console.log('1秒后'), 1000);
clearTimeout(id); // 取消定时器与 this
setTimeout(fn, 1000) 中 fn 的 this 是全局对象(严格模式 undefined),不是外层 this——回调场景用箭头函数解决,机制见 作用域与闭包。
网络请求:fetch
fetch 是浏览器原生异步请求 API,返回 Promise,配合 async/await 使用:
async function loadUser(id) {
const res = await fetch(`/api/users/${id}`);
if (!res.ok) throw new Error(`HTTP ${res.status}`); // fetch 不抛 4xx/5xx
const user = await res.json(); // 解析 JSON
return user;
}
// POST 请求
const res = await fetch('/api/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: '张三' }),
});fetch vs XHR
fetch 基于 Promise 链式/await 编写,比传统 XMLHttpRequest 简洁;跨域(CORS)由服务端响应头控制,前端配置见 npm包管理 中的 cors 中间件。浏览器并发上限(同域约 6 个连接)是性能瓶颈,多请求用 Promise.all 分批(见 异步编程)。
DOM 操作与 JavaScript语法 的数据类型、作用域与闭包 的事件回调机制、异步编程 的请求编排共同构成浏览器端开发基础。