必须缓存DOM查询结果,因每次调用querySelector等方法都要遍历DOM树,造成同步开销;应在初始化阶段一次性查询并用const声明变量,仅缓存高频且确定存在的元素。

直接把查到的 DOM 元素存成变量,后续所有操作都用这个变量,别再反复调用 document.getElementById、querySelector 这类方法——这是最简单也最有效的缓存方式。
为什么必须缓存 DOM 查询结果
每次调用 document.querySelector 或 getElementById,浏览器都要遍历整个 DOM 树(或部分子树),这个过程是同步且不可忽略的开销。尤其在以下场景中,重复查询会明显拖慢响应速度:
- 事件回调里多次访问同一元素(比如点击按钮后连续修改样式和内容)
- 循环中反复查找某个容器或列表项
- 定时器(
setInterval)内频繁读取元素状态 - 动画帧(
requestAnimationFrame)中实时获取尺寸或位置
怎么正确缓存:三步到位
缓存不是“随便存一个变量”,关键在于时机和作用域:
-
在初始化阶段就查好:页面加载完成(
DOMContentLoaded)或组件挂载时执行一次查询,赋值给常量或模块级变量 -
用
const声明引用:DOM 元素本身不会变,变量只需保存一次引用,避免误赋新值 - 按需缓存,不盲目全存:只缓存高频使用、确定存在的元素;不确定是否存在的,先加存在性判断再缓存
示例:
立即学习“Java免费学习笔记(深入)”;
const header = document.querySelector('header');
const productList = document.getElementById('product-list');
const searchInput = document.querySelector('.search-input');
// 后续所有操作都基于这几个变量
header.classList.add('scrolled');
productList.innerHTML = generateProductHTML(data);
searchInput.focus();
哪些情况容易忽略缓存
有些写法看着自然,其实暗藏重复查询陷阱:
- 链式调用中重复查父元素:
document.querySelector('.form').querySelector('input')→ 应先缓存.form - 条件分支里各自查同一个元素:
if (x) document.getElementById('msg').textContent = 'a'; else document.getElementById('msg').textContent = 'b'→ 提前缓存msgEl - 函数内部每次调用都查:
function updateStatus() { const el = document.getElementById('status'); el.textContent = 'loading'; }→ 把el提到函数外或用闭包封装
配合其他优化效果更好
缓存只是第一步,搭配这些做法能进一步减少重排重绘:
- 对同一个元素批量改样式时,优先用
className或classList替代逐个设style.xxx - 需要多次增删子节点,先用
documentFragment组装,再一次性插入 - 临时隐藏元素做批量操作?用
display: none或visibility: hidden减少布局影响



















