反向遍历_子元素数量和遍历子元素

编者按:本文作者:贺师俊(网名 Hax),360 高级前端架构师,十多年来一直活跃在前端和 JavaScript 社区。对多项 Web 标准有微小贡献,对 Groovy 语言并间接对 Swift 语言有微小贡献,近年来参与了诸多 ECMAScript 新草案的讨论。曾设计和实现 Jedi 语言并用于生产环境,对自研编程语言略有一点实践经验。三次担任 QCon 出品人并获得「优秀出品人」荣誉,也经常在其他众多技术活动中担任讲师、嘉宾和主持人。

如何得到一个元素的子元素数量?

有基本 DOM API 常识的前端程序员可能第一时间想到 element.childNodes.length 。不过 childNodes 既包含元素节点也包含文本节点,所以你还需要遍历过滤,不太符合要求。

如果我们仔细查看DOM spec,会发现两个符合要求的 API:

  • element.children.length

  • element.childElementCount

那么问题来了,为什么同一件事情需要两个API呢?

children 返回所有子元素,看上去是比较有用的,那 childElementCount 是不是多余的呢?而且如果仔细看文档,跟 childElementCount 一起的 Element Traversal API (https://www.w3.org/TR/ElementTraversal/)还有一堆其他接口,包括 firstElementChild 、 lastElementChild 、 previousElementSibling 、nextElementSibling 。这些接口是否多余的呢?在实践中和 children 相比,孰优孰劣?

这是一个好问题。

我们分几点来说。

首先我们可以发现 previousElementSibling, nextElementSibling 并不是多余的,因为 children 接口做不到同样的事情。

其次 firstElementChild, lastElementChild 虽然等价于 children[0] 和 children[children.length - 1] ,但是前者避免了先生成一个 children 对象,所以是更直接且性能更好的接口(尤其是对 lastElementChild 来说)。

注意 children 是一个 live collection,按照通常的 DOM 实现来说,使用 firstElementChild 配合 nextElementSibling 的正向遍历(或者 lastElementChild 配合 previousElementSibling 的反向遍历)可以比基于children索引的遍历获得更好的性能。

for (let i = 0; i < e.children.length; ++i) {

    process(e.children[i])

}

// better

for (let child = e.firstElementChild; child != null; child = child.nextElementSibling) {

    process(child)

}

最后,childElementCount 确实是多余的接口。【小彩蛋:如果你打开 spec 的源码会发现有一句注释:】

Element Traversal API 是在2007年左右开始制定的,本源来自于 SVG Micro DOM 的需求(而不像其他 DOM 新接口主要来自于浏览器厂商联盟 WHATWG),原本是没有 childElementCount 属性的。当时从 SVG 工作组接手的 WebAPI 工作组加入了这个属性,但并没有将 children 属性(比较老的前端应该知道这原本是 IE 的私有接口)标准化列入议程。仅仅从 traversal 需求来说并不需要 children 属性,但某些次要需求其实需要 children count(参见ElementTraversal API 的代码示例(https://www.w3.org/TR/ElementTraversal/#example-3.2)),所以就加了这个属性。但 children 属性标准化之后,这个 childElementCount 就变得多余了。

其实在2011年左右,主导 HTML/DOM 标准制定的 WHATWG 有动议要删除这个属性,但是因为这个属性在之前的3年中已经在所有主流浏览器里实现了(2008年到2010年间,Chrome 1+、FF 3.5+、Safari 4+、IE9+ 都实现了此属性——是的,尽管很可能到今天还有许多前端并不知道这个接口的存在) ,所以到2012年年底的时候最后决定还是不删除了。

最后,现在的 DOM 标准应该直接看 WHATWG DOM Standard (https://dom.spec.whatwg.org/) ,Element Traversal已经属于上一代标准了。

关于奇舞周刊

《奇舞周刊》是360公司专业前端团队「奇舞团」运营的前端技术社区。关注公众号后,直接发送链接到后台即可给我们投稿。

e3a6a118f5d6e249b8fa0f7cbb3b34d8.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值