原生DOM探究 -- NodeList v.s. HTMLCollection

涉及获取元素的主要API

在获取原生DOM元素的时候,主要涉及这几个DOM API(链接为Living Standard):

注:计划取代NodeListHTMLCollectionElements目前并无广泛实现

基础知识 -- NodeList v.s. HTMLCollection

在不同版本的浏览器中,如果使用获取多元素的DOM方法,有的会得到NodeList(多为旧浏览器),有的会得到HTMLCollection(多为新浏览器),所以有必要了解一下这两者的区别。

关于这两个类型的差异,在Stackoverflow上有一个不错的问答

其实,只要先看看Living Standard中这两个类型的IDL,便能猜出大概了。NodeList的IDL如下:

interface NodeList {
  getter Node? item(unsigned long index);
  readonly attribute unsigned long length;
  iterable<Node>;
};

HTMLCollection的IDL如下:

interface HTMLCollection {
  readonly attribute unsigned long length;
  getter Element? item(unsigned long index);
  getter Element? namedItem(DOMString name);
};

相同点:

  1. 它们都有length属性
  2. 都有元素的getter,叫做item

不同点:

  1. NodeList的元素是Node,HTMLCollection的元素是Element

    Element继承自Node,是Node一种,在HTML中,它一般是HTML元素(比如<p><a>之类的标签创建出来的对象)。而Node作为父类,除了Element还有一些其他子类,比如HTML元素内的文本对应的Text,文档对应的Document,注释对应的Comment

    HTMLCollection里,只有Element,而NodeList里可以有ElementTextComment等多种元素。按说如果获取元素返回的列表里只有Element,那这两种类没多大区别,但事实上很多时候浏览器会将解析HTML文本时得到的TextComment一并放进列表里放回。比如说下面这一段代码

    <div>
        <!-- Comment -->
        <p>This is Some Text</p>
    </div>

    若将这个div的子元素放在列表里返回,那么如果是作为NodeList返回,浏览器最多可以给这个列表5个元素(不同浏览器可能不同)

    1. 一个<div>和注释间的断行和空格(或tab)作为text node(没错,标签之间的空白符号也可以被解析为text node)
    2. 注释作为comment node
    3. 注释和<p>之间的断行和空格(或tab)作为text node
    4. p作为element
    5. </p></div>之间的断行和空格(或tab)作为text node

    因此NodeList里可能会有很多一般DOM操作不需要的text node和comment node需要处理。而HTMLCollection则简单多了,只有<p>这一个元素,这也是比较符合大多数人直觉的结果。

  2. HTMLCollection还有一个namedItem方法,可以快速获取其中元素。假设有这样一段HTML:
    <div>
        <!-- Comment -->
        <p>This is Some Text</p>
        <img name="test" src="test.jpg">
    </div>

    那么假设得到了这个div的子元素构成的HTMLCollection,叫做list,那么使用list.namedItem("test")就可以直接得到里面的img元素。

    查找顺序参考Living Standard,但是在现实中不是所有浏览器都遵循标准。比如标准规定如果有多个拥有相同id或者name的元素,只要返回第一个,但chrome和opera会将它们放在一个HTMLCollection或者NodeList里一并返回,参见MDN

从IDL看不出来的还有如下几点

  1. 这两个类都是“live”的。对其中元素进行操作,会实时反映到DOM中(也因此如果一次性直接在这类列表上进行多个DOM操作的话,带来的开销会很大)。
  2. itemnamedItem都可以通过[]的缩写进行调用,有的浏览器还支持用()的缩写进行调用(也就是可以list[index]list[key]或者list(index)list(key)),以及直接用dot notation调用namedItem(比如list.key)。
  3. 部分浏览器支持对NodeList调用namedItem或间接通过[]()、dot notation来调用namedItem,但由于各浏览器支持不同,最好不对NodeList做这种操作。
  4. IE8及以下版本浏览器中,注释属于HTMLCommentElement,算作Element,因此会出现在HTMLCollection里。
时间: 2024-10-11 21:34:37

原生DOM探究 -- NodeList v.s. HTMLCollection的相关文章

【转】原生DOM探究 -- NodeList v.s. HTMLCollection

原文链接:http://www.cnblogs.com/joyeecheung/p/4067927.html 涉及获取元素的主要API 在获取原生DOM元素的时候,主要涉及这几个DOM API(链接为Living Standard): Node及对应集合NodeList Element(继承Node)及对应集合HTMLCollection Document(继承Node) 注:计划取代NodeList和HTMLCollection的Elements目前并无广泛实现 基础知识 -- NodeLis

NodeList接口,HTMLCollection接口

原文地址:https://wangdoc.com/javascript/ 节点都是单个对象,有时需要一种数据结构,能够容纳多个节点.DOM提供两种节点集合,用于容纳多个节点:NodeList和HTMLCollection. 这两种集合都属于接口规范.许多DOM属性和方法,返回的结果是NodeList实例或HTMLCollection实例.主要区别是,NodeList可以包含各种类型的节点,HTMLCollection只能包含HTML元素节点. NodeList接口 概述 NodeList实例是一

javascript:NodeList 接口,HTMLCollection 接口

原文章:https://wangdoc.com/javascript/index.html NodeList 接口,HTMLCollection 接口 节点都是单个对象,有时需要一种数据结构,能够容纳多个节点.DOM 提供两种节点集合,用于容纳多个节点:NodeList和HTMLCollection. 这两种集合都属于接口规范.许多 DOM 属性和方法,返回的结果是NodeList实例或HTMLCollection实例.主要区别是,NodeList可以包含各种类型的节点,HTMLCollecti

随机色&原生DOM筛选元素

function colorRandom1(){ var r = Math.floor(Math.random()*51+200); var g = Math.floor(Math.random()*51+200); var b = Math.floor(Math.random()*51+200); return 'rgb('+r+','+g+','+b+')'; } var div = document.body.getElementsByTagName('div')[0]; div.styl

JQ对象和原生DOM对象

相同点:两者本质上都是DOM元素. 不同点:JQ对象是在原生DOM对象上进行了一次封装,使开发人员使用起来更简洁.高效. 两者之间用法也完全不同,很说初学者经常混淆. 其实区分两者并不难, 1.语法不一样,JQ对象都是以$开头的,API也不一样(具体请查询JQ手册).     比如:$('#a').html()    //这样写就可以拿到id 叫 a里面的内容. 如果   $('#a').innerHTML  // 这样写就会报错,而且拿不到任何内容,原因就是$('#a')是JQ对象,而inne

PHP原生DOM对象操作XML&#39;代码&#39;

对于操作XML类型文件,PHP内置有一套DOM对象可以进行处理.对XML的操作,从创建.添加到修改.删除都可以使用DOM对象中的函数来进行. 创建 创建一个新的XML文件,并且写入一些数据到这个XML文件中. /* * 创建xml文件 */ $info = array( array('obj' => 'power','info' => 'power is shutdown'), array('obj' => 'memcache','info' => 'memcache used t

用原生dom的方法获取class对象(很简单实用)

话不多说,直接上代码,用的是for(var i in array) 1 <!doctype html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>用原生dom的方法获取class对象(很简单实用)</title> 6 <style> 7 .ca{background:red;padding:20px;} 8 .js{border:1px so

Jquery的dom操作与原生dom的转换

本片文章包含了 jquery常见dom操作. q与原生dom对象的区别与转换 伪数组对象的知识 如有错误,烦请指正. 增 以下方法共性:可以一次添加多个内容,内容可以是DOM对象.HTML string. jQuery对象 创建元素 var obj = $('<div class="test"><p><span>Done</span></p></div>'); 两种方法可以创建元素 直接写入html 传入一个原生d

Virtual DOM 真的比操作原生 DOM 快吗?

1. 原生 DOM 操作 vs. 通过框架封装操作. 这是一个性能 vs. 可维护性的取舍.框架的意义在于为你掩盖底层的 DOM 操作,让你用更声明式的方式来描述你的目的,从而让你的代码更容易维护.没有任何框架可以比纯手动的优化 DOM 操作更快,因为框架的 DOM 操作层需要应对任何上层 API 可能产生的操作,它的实现必须是普适的.针对任何一个 benchmark,我都可以写出比任何框架更快的手动优化,但是那有什么意义呢?在构建一个实际应用的时候,你难道为每一个地方都去做手动优化吗?出于可维