id查找是o(1)哈希索引,class依赖css引擎遍历匹配;id重复时getelementbyid只返首个,class多空格会解析出空类名,classlist操作比classname拼接更安全。

id 和 class 在 DOM 查找与样式绑定中的实际差异
id 是浏览器内部用哈希表索引的,document.getElementById("x") 是 O(1) 时间复杂度;而 class 依赖 CSS 选择器引擎,document.querySelector(".x") 或 document.getElementsByClassName("x") 需遍历匹配,尤其在深层嵌套或节点量大时有明显延迟。
常见错误现象:一个页面中写了多个 id="header",getElementById 只返回第一个,HTML 验证器会警告但 JS 不报错;class="btn primary" 中若有两个空格(如 class="btn primary"),会被解析为三个类名:["btn", "", "primary"],导致 classList.contains("primary") 返回 false。
- 用
classList.add("active")操作类名,比直接改className += " active"更安全(避免重复、多余空格) -
id命名必须以字母或下划线开头,不能以数字起始;大小写敏感,id="Header"≠id="header" -
class支持多值,但空格是分隔符,不是装饰——中间多一个空格就多一个空类名
data-* 属性读写时的命名陷阱与类型处理
data- 是唯一被规范允许的自定义数据通道,但它不是“随便写完 JS 就能拿”的管道。HTML 中写 data-user-id="123",JS 里必须通过 dataset.userId 访问(连字符转驼峰,首字母小写),dataset.userid 或 dataset.Userid 都拿不到值。
容易踩的坑:
- 属性名含数字开头,比如
data-1st-place="gold",JS 中无法用dataset.1stPlace(变量名非法),得用dataset["1st-place"] -
data-后只能跟 ASCII 字母、数字、连字符(-)、点(.)、下划线(_),data-user:name会被浏览器静默忽略 - 所有值都是字符串,哪怕
data-count="0",取出来也是"0",需要手动转类型:Number(el.dataset.count)或parseInt(el.dataset.count, 10)
hidden 属性与 display: none 的行为区别
hidden 是布尔属性,写成 hidden、hidden="" 或 hidden="hidden" 效果一致,等价于 display: none;但 hidden="until-found" 是个例外,它等价于 content-visibility: hidden,元素仍参与布局(占位),只是内容不可见且不渲染子树。
使用场景:
- 动态控制显隐时,
hidden比切换style.display更语义明确,也更易被辅助技术识别 -
hidden对<script></script>、<meta>等非渲染元素无效,浏览器会忽略,但不报错 - 不要对
或使用hidden,部分浏览器行为未定义
tabindex、lang、title 这几个“低调但关键”的全局属性
tabindex 控制键盘 Tab 导航顺序,但注意:默认值不是 0,而是未设置时无焦点能力;要让一个 <div> 可聚焦,必须显式写 <code>tabindex="0"(不是 tabindex 或 tabindex="1")。
lang 和 title 看似简单,却直接影响可访问性和 SEO:
-
lang="zh-CN"告诉屏幕阅读器用中文朗读,lang缺失时可能用错语音引擎 -
title不只是悬停提示,它也是辅助技术读出的补充说明,但别滥用——太多title会让屏幕阅读器变得啰嗦 -
tabindex="-1"允许 JS 主动聚焦(el.focus()),但用户无法用 Tab 键到达,适合模态框首次打开时聚焦主按钮
真正稳定、跨所有 HTML 元素可用的核心全局属性其实就这几个:id、class、data-*、title、lang、dir、style、tabindex。其余像 contenteditable、draggable、exportparts 都有明确的适用边界,强行加到不支持的标签上只会被忽略。











