DOM是浏览器解析HTML后生成的内存中对象树,每个节点对应可编程JS对象,不等于原始HTML字符串;获取元素优先用getElementById、querySelector、querySelectorAll;修改内容用textContent或innerHTML,属性用点号或setAttribute,样式用className或classList;事件需确保DOM就绪,动态元素用事件委托。

DOM 是网页的树状结构映射,不是 HTML 字符串
JavaScript 中的 DOM(Document Object Model)是浏览器将 HTML 解析后生成的内存中对象树,每个节点(如 <div>、<p>、文本内容)都对应一个可编程的 JS 对象。它不等于原始 HTML 源码——比如你用 JS 修改了 innerHTML,DOM 树会立刻更新,但 document.documentElement.outerHTML 返回的是当前实时状态,未必和初始 HTML 一致。
常见误解:以为 document.getElementById('x') 返回的是字符串或 HTML 片段。实际返回的是一个 Element 对象,有属性(id、className)、方法(appendChild()、remove())和事件接口(addEventListener())。
获取元素最常用且安全的三种方式
优先按场景选,别无脑用 querySelector:
-
document.getElementById('myBtn')—— 唯一 ID,最快,返回单个 Element 或 null -
document.querySelector('.nav-link[data-active="true"]')—— 支持任意 CSS 选择器,只返回第一个匹配项;若没匹配,返回 null(不是空数组!) -
document.querySelectorAll('input[type="checkbox"]')—— 返回NodeList(类数组),可用forEach,但不能直接用map(需转成数组:[...nodeList].map(...))
注意:getElementsByClassName 和 getElementsByTagName 返回的是动态 HTMLCollection,后续 DOM 变化会实时反映在该集合中,容易引发无限循环或意外重读 —— 新项目尽量避开。
立即学习“Java免费学习笔记(深入)”;
修改内容、属性和样式的三类典型操作
不同目的必须用不同 API,混用会导致不可见副作用:
- 改显示文字:
el.textContent = '新标题'(安全,防 XSS);el.innerHTML = '<em>强调</em>'(危险,仅当可信 HTML 才用) - 设属性:
el.setAttribute('disabled', '')或更推荐el.disabled = true(布尔属性优先用点号赋值) - 改样式:
el.style.color = '#333'(仅内联样式);批量改样式优先用el.classList.add('active')或el.className = 'btn btn-primary'
性能提示:频繁修改多个样式时,避免连续写 el.style.xxx,应改用 el.className 切换预定义 CSS 类,或用 el.setAttribute('style', '...') 一次性写入。
事件绑定必须等元素存在,否则拿到 null
脚本执行早于 DOM 加载完成,是 getElementById 返回 null 的最常见原因:
- 把 JS 放在
</body>前(最简单有效) - 用
DOMContentLoaded事件:document.addEventListener('DOMContentLoaded', () => { /* 此时 DOM 已就绪 */ }); - 不推荐
window.onload—— 它等图片、CSS 等全部资源加载完,延迟更高
另一个坑:给未来才插入的元素(如 AJAX 加载的列表项)绑定事件,不要反复绑定,改用事件委托:
document.querySelector('#list').addEventListener('click', e => { if (e.target.matches('.item-delete')) { /* 处理删除 */ } });
DOM 操作本身很简单,真正的复杂性来自时机判断、引用生命周期和事件流控制——比如移除元素后还试图访问它的 parentNode,或忘记解绑事件导致内存泄漏。这些细节比语法更值得花时间确认。











