应使用 lastElementChild 而非 lastChild 获取最后一个子元素,因 lastChild 常返回空白文本节点;兼容 IE 时可用 children[length-1] 降级处理。

Node.lastChild 不能直接用来定位“最后一个子元素”,它返回的是最后一个子节点——极大概率是空白文本节点,不是你要的 <div> 或 <p>。想快速拿到编辑器当前块的最后一个子元素,得绕开它。
为什么 lastChild 在编辑器里几乎总是错的
HTML 编辑器(比如 contenteditable 容器)的 DOM 结构中,用户敲回车、空格、粘贴内容后,元素之间极易生成不可见的文本节点。哪怕你只写了:
<div contenteditable="true"> <p>第一段</p> <p>第二段</p> </div>
实际 lastChild 拿到的很可能是换行符或空格构成的 #text 节点,nodeType === 3,不是 Element。
-
lastChild包含所有节点类型:元素、文本、注释 - 编辑器里文本节点出现频率远高于静态页面
-
lastChild.nodeName很可能返回"#text",不是"P"或"DIV"
应该用 lastElementChild —— 但注意兼容性
Element.lastElementChild 是专为这个问题设计的:它跳过所有非元素节点,只返回最后一个子元素节点。
立即学习“前端免费学习笔记(深入)”;
- 在现代浏览器中稳定支持(Chrome 29+、Firefox 3.5+、Safari 4+、Edge 12+)
- IE 11 及更早版本不支持,若需兼容 IE,必须降级处理
- 如果容器下没有子元素(比如刚清空),返回
null,需判空
示例:
const editor = document.querySelector('[contenteditable]');
const lastEl = editor.lastElementChild; // ✅ 正确拿到最后一个 <p>、<div> 等兼容 IE 的 fallback 写法
当必须支持 IE 时,不能依赖 lastElementChild,但也不必遍历全部 childNodes。可以用 children 集合(IE6+ 支持,且只含元素节点):
-
element.children是 HTMLCollection,只包含元素子节点 -
element.children.length就是子元素个数 -
element.children[element.children.length - 1]就是最后一个子元素
安全写法:
function getLastChildElement(el) {
if (el.lastElementChild != null) return el.lastElementChild;
return el.children.length > 0 ? el.children[el.children.length - 1] : null;
}编辑器场景下的典型误用和修复
常见错误是把 lastChild 和 lastElementChild 混用,尤其在监听 input 或 keydown 后立刻读取:
- 用户按 Enter 后,DOM 还没重排完成?不,DOM 已更新,但新增的是
<div><br></div>或空<p></p>,其lastChild仍是<br>或空文本 - 想判断是否在最后一段末尾按了 Enter?别看
lastChild,应检查getSelection().focusNode.parentElement === lastElementChild - 插入新块前要克隆最后一段样式?用
lastElementChild获取目标元素,再读computedStyle或className
真正容易被忽略的点:编辑器内容可能被外部脚本动态插入注释节点(比如某些富文本库加的 marker),lastChild 会意外命中它们;而 lastElementChild 和 children 都天然免疫这类干扰。


















