先记住这个答案
firstChild 是 Node 属性,返回紧邻的第一个子节点,类型不限,包括文本节点(如换行缩进)和注释节点。firstElementChild 是 Element 属性,仅返回第一个子元素,忽略文本与注释。两者在无对应子节点时都返回 null。实际开发中若需遍历元素,应用 firstElementChild 避免空白文本干扰。
- firstChild 含文本和注释节点
- firstElementChild 仅元素节点
- 两者无匹配时均返回 null
节点过滤机制与空白敏感性
DOM 将文档结构表示为节点树,子节点包括元素、文本、注释等。firstChild 读取的是 Node 接口的 childNodes 列表首个项,因此若元素内部有空白(如换行缩进),该空白会作为文本节点出现并成为 firstChild。这不仅影响读取,也会使判断逻辑产生意外结果。
firstElementChild 则直接返回 Element 类型的首个子节点,其基于 children 集合,该集合只包含元素节点。浏览器解析时会将相邻文本(即使仅空白)合并为单一文本节点,因此 firstChild 常返回一个包含空格的文本节点。若想获取首个实际元素,使用 firstElementChild 可避免大量手动跳过 Text 节点的代码。
导航菜单遍历时的空白杂质
假设有一个 <ul> 包含多个 <li>,HTML 源码中为可读性加了换行和缩进。此时 ul.firstChild 是一个仅含空白的文本节点,而 ul.firstElementChild 则是第一个 <li>。如果我们用循环从 firstChild 开始通过 nextSibling 遍历,每步都要判断 nodeType === Node.ELEMENT_NODE,否则会误将空白文本当作列表项操作。
实际项目中的导航列表通常大量使用 li 的点击事件绑定与样式操作。改用 firstElementChild 后,配合 nextElementSibling 即可只遍历元素,代码更简洁且不依赖 HTML 源码是否紧凑。这种差异在由渲染引擎生成的动态内容中同样存在,因此统一用 Element 遍历属性是更稳健的写法。
无子节点时的返回及隐性陷阱
当元素没有任何子节点(包括文本)时,firstChild 与 firstElementChild 都为 null。但常见误解是若元素为空标签且无缩进则二者相等,可一旦手写格式化 HTML,空白节点即产生差异。此外,注释节点也是 Node,会被 firstChild 捕获,而 firstElementChild 会忽略注释。
处理 null 必须区分含义:若仅需元素,用 firstElementChild 判断结果是否 null 即可。若需检测是否存在文本内容,则必须用 firstChild 再判断 nodeType。在动态创建节点时如使用 document.createTextNode 添加文本,那么 firstChild 可返回该文本节点,而 firstElementChild 仍为 null——这种不对称常导致逻辑错误,应当依据具体需求选择正确属性。
容易答错的地方
- 误以为 firstChild 总是返回元素
- firstChild 返回 childNodes 的第一项,可能是 Text、Comment 等非元素节点。HTML 中常见的空白缩进就会让 firstChild 变成文本节点,因此不能直接当作元素操作。
- 认为无子节点时两者不同
- 当元素完全没有子节点(连空白也没有)时,firstChild 与 firstElementChild 均返回 null,不是 undefined 也不是抛异常。但在有空白文本的情况下,firstChild 会返回 Text 节点,这是常见混乱点。
面试官还会怎么问?
在事件委托中,如何可靠地获取首个元素子节点?
使用 firstElementChild,它天然过滤空白和注释。若需兼容老环境,可以遍历 childNodes 检查 nodeType === 1,但现代浏览器和广泛支持已足够,直接使用即可。
firstChild 和 childNodes[0] 是否等价?
完全等价,firstChild 是 childNodes[0] 的更友好别名。同样,firstElementChild 也可写作 children[0],后者在 children 为空时返回 undefined,而 firstElementChild 返回 null,需注意类型差异。
如何判断元素是否有子文本节点?
检查 firstChild 且其 nodeType === Node.TEXT_NODE。但由于空白节点也视为文本,通常需要先确认非空字符串,例如 firstChild.nodeValue.trim() !== '' 才表示含实际内容。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。