优先使用ID和data-*属性选择器,因其查找复杂度为O(1)且唯一可控;控制层级≤3层,避免回溯;限定查询上下文并缓存高频选择器,可提升性能3–6.8倍。

直接用 ID 或带 data 属性的单一选择器,比嵌套多层的 CSS 路径快 3–5 倍。关键不是“写得对不对”,而是浏览器匹配时少走多少回溯路径。
优先使用 ID 和 data-* 属性选择器
ID 是浏览器原生哈希索引,查找时间复杂度为 O(1);data-id 或 data-cell 等属性也比类名更唯一、更可控。
- 避免:
document.querySelector('div.container > section.main > article.content h2.title') - 推荐:
document.querySelector('#article-title')或document.querySelector('[data-role="title"]') - 若 DOM 不可改,可在 JS 初始化阶段动态加
id或data-属性,一次设置,长期受益
控制选择器层级,不超过 3 层
浏览器从右向左匹配,层级越深,回溯验证越多。5 层嵌套在低端设备上实测慢 3–5 倍。
- 把
.card .card__header .card__title改成.card__title(BEM 命名保障语义) - 用
.modal-close-btn替代.modal.is-open .close-btn,剥离状态依赖 - 慎用
:not()、*、+,它们会触发额外全量扫描
限定查询上下文,避免全局遍历
在大型文档中,document.querySelectorAll 每次都遍历整棵 DOM 树;而限定作用域后,只查子树,性能提升明显。
- 优化前:
document.querySelectorAll('.edit-button') - 优化后:
listContainer.querySelectorAll('.edit-button')(listContainer是已缓存的父容器) - 进一步可结合
getElementsByClassName或getElementsByTagName,它们比querySelectorAll快约 3 倍
预编译或缓存高频选择器逻辑
对反复使用的复杂路径,不要每次调用都解析;可提前生成并复用定位函数。
- 对静态结构,缓存父容器:
this.$body = document.getElementById('app').firstElementChild - 对动态内容,用
MutationObserver监听新增节点,按需绑定轻量级选择器 - 若使用 JSONSelect 类工具处理结构化数据,务必调用
JSONSelect.compile()预编译,实测提速 6.8 倍










