querySelectorAll 返回的是一个 Static Node List,而 getElementsBy 系列的返回的是一个 Live Node List。

看看下面这个经典的例子 [5]:

// Demo 1
var ul = document.querySelectorAll('ul')[0],
lis = ul.querySelectorAll("li");
for(var i = 0; i < lis.length ; i++){
ul.appendChild(document.createElement("li"));
} // Demo 2
var ul = document.getElementsByTagName('ul')[0],
lis = ul.getElementsByTagName("li");
for(var i = 0; i < lis.length ; i++){
ul.appendChild(document.createElement("li"));
}

因为 Demo 2 中的 lis 是一个动态的 Node List, 每一次调用 lis 都会重新对文档进行查询,导致无限循环的问题。
而 Demo 1 中的 lis 是一个静态的 Node List,是一个 li 集合的快照,对文档的任何操作都不会对其产生影响。

但为什么要这样设计呢?
其实,在 W3C 规范中对 querySelectorAll 方法有明确规定 [6]:

The NodeList object returned by the querySelectorAll() method must be static ([DOM], section 8).

那什么是 NodeList 呢?
W3C 中是这样说明的 [7]:

The NodeList interface provides the abstraction of an ordered collection of nodes, without defining or constraining how this collection is implemented. NodeList objects in the DOM are live.

所以,NodeList 本质上是一个动态的 Node 集合,只是规范中对 querySelectorAll 有明确要求,规定其必须返回一个静态的 NodeList 对象。

我们再看看在 Chrome 上面是个什么样的情况:

document.querySelectorAll('a').toString();    // return "[object NodeList]"
document.getElementsByTagName('a').toString(); // return "[object HTMLCollection]"

这里又多了一个 HTMLCollection 对象出来,那 HTMLCollection 又是什么?

HTMLCollection 在 W3C 的定义如下 [8]:

An HTMLCollection is a list of nodes. An individual node may be accessed by either ordinal index or the node's name or id attributes.
Note: Collections in the HTML DOM are assumed to be live meaning that they are automatically updated when the underlying document is changed.

实际上,HTMLCollection 和 NodeList 十分相似,都是一个动态的元素集合,每次访问都需要重新对文档进行查询。两者的本质上差别在于,HTMLCollection 是属于 Document Object Model HTML 规范,而 NodeList 属于 Document Object Model Core 规范。
这样说有点难理解,看看下面的例子会比较好理解 [9]:

var ul = document.getElementsByTagName('ul')[0],
lis1 = ul.childNodes,
lis2 = ul.children;
console.log(lis1.toString(), lis1.length); // "[object NodeList]" 11
console.log(lis2.toString(), lis2.length); // "[object HTMLCollection]" 4

NodeList 对象会包含文档中的所有节点,如 Element、Text 和 Comment 等。
HTMLCollection 对象只会包含文档中的 Element 节点。
另外,HTMLCollection 对象比 NodeList 对象 多提供了一个 namedItem 方法。

所以在现代浏览器中,querySelectorAll 的返回值是一个静态的 NodeList 对象,而 getElementsBy 系列的返回值实际上是一个 HTMLCollection 对象 。

querySelector.. 方法相比 getElementsBy..的更多相关文章

  1. querySelectorAll 方法相比 getElementsBy 系列方法区别

    最近有人问到querySelectorAll 方法相比 getElementsBy 系列方法区别,一时没想起来说些什么,今天查下文档,总结一下它们的区别,以便自己理解. 1. W3C 标准queryS ...

  2. querySelector系列方法相比 getElementsBy 系列方法有什么区别?

    querySelector 和  querySelectorAll 相比下面这些方法有什么区别? getElementsByTagName getElementsByClassName getElem ...

  3. [label][转载][JavaSript]querySelectorAll 方法相比 getElementsBy 系列方法有什么区别?

     轉載出處: http://www.zhihu.com/question/24702250 querySelectorAll 相比下面这些方法有什么区别? getElementsByTagName g ...

  4. querySelectorAll 方法相比 getElementsBy 系列方法有什么区别

    感谢 http://www.zhihu.com/question/24702250 简生 的回答 1. W3C 标准 querySelectorAll 属于 W3C 中的 Selectors API ...

  5. getElementById和querySelector方法的区别

    "querySelector 属于 W3C 中的 Selectors API 规范 .而 getElementsBy 系列则属于 W3C 的 DOM 规范" 1.区别 getXXX ...

  6. querySelector() 方法

    返回文档中匹配指定 CSS 选择器的一个元素. 虽然IE8中没有getElementsByClassName()但可以用querySelector()代替 注意: querySelector() 方法 ...

  7. HTML DOM querySelector() 方法

     Document 对象 实例 获取文档中 id="demo" 的元素: document.querySelector("#demo"); <!DOCTY ...

  8. Javascript实例教程:querySelector()方法接受一个CSS查询并返回匹配模式的第一个子孙元素,如果没有匹配的元素则返回null。

    文章简介:querySelector()方法接受一个CSS查询并返回匹配模式的第一个子孙元素,如果没有匹配的元素则返回null. querySelector()方法接受一个CSS查询并返回匹配模式的第 ...

  9. getElementsBy 系列方法相比querySelector系列的区别

    最近在做的项目中,使用querySelectorAll获取了同class名的元素后,绑定onmouseover事件和onmouseout后,多次在几个元素上移入移出操作时,控制台出现了报错的问题,最后 ...

随机推荐

  1. 事后调试.ZC资料

    1.查了一下,Delphi 程序 可以生成 map文件,可以用来 根据崩溃的内存报错 定位出错的代码位置 2.但是,Delphi程序 无法再崩溃的时候 生成dump文件 (这个不一定,研究了再说.记得 ...

  2. [javascript]jQuery绑定事件方法:on()

    语法: $(selector).on(event,childSelector,data,function) on(event,childSelector,data,function):在被选元素及子元 ...

  3. C++ substr 和 substring

    功能相似,但参数不同 substr(start,length); substring(start,end);

  4. 利用python 模块读取csv文件信息

    还有一个比较简单的方法 # -*- coding=utf-8 -*- import pandas as pddf = pd.read_csv("20170320094630.csv" ...

  5. Kinect研究文档

    1.  Kinect主要脚本介绍 1.1  KinectManager脚本 控制传感器并轮询数据流, 下图是参数详解: 公共API网址:https://ratemt.com/k2gpapi/annot ...

  6. Android----- 版本更新和 服务器下载新版本APK并安装

    前段时间有朋友问我版本更新的问题,所以来写一篇版本更新和APK下载并安装的博客. 版本更新,几乎在所有的项目中都用的到,一般是这样的流程,当进入APP首页是便会检测版本是否为最新版本,不是则提示你下载 ...

  7. python使用安装ipdb

    1.安装 python3版本直接执行pip install ipdb命令安装 python2.7版本的需要指定ipdb的版本 pip install ipdb==0.10.2 等号后面的就是版本,因为 ...

  8. leetcode 720. Longest Word in Dictionary

    Given a list of strings words representing an English Dictionary, find the longest word in words tha ...

  9. 【转】线程池体系介绍及从阿里Java开发手册学习线程池的正确创建方法

    jdk1.7中java.util.concurrent.Executor线程池体系介绍 java.util.concurrent.Executor : 负责线程的使用与调度的根接口  |–Execut ...

  10. Java--------------Windows下Redis的安装使用

    摘要 redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合).zset(sorted s ...