1. W3C 标准
querySelectorAll 属于 W3C 中的 Selectors API 规范 [1]。而 getElementsBy 系列则属于 W3C 的 DOM 规范 [2]。

2. 浏览器兼容
querySelectorAll 已被 IE 8+、FF 3.5+、Safari 3.1+、Chrome 和 Opera 10+ 良好支持 。
getElementsBy 系列,以最迟添加到规范中的 getElementsByClassName 为例,IE 9+、FF 3 +、Safari 3.1+、Chrome 和 Opera 9+ 都已经支持该方法了。

3. 接收参数
querySelectorAll 方法接收的参数是一个 CSS 选择符。而 getElementsBy 系列接收的参数只能是单一的className、tagName 和 name。代码如下 [3]:

var c1 = document.querySelectorAll('.b1 .c');
var c2 = document.getElementsByClassName('c');
var c3 = document.getElementsByClassName('b2')[0].getElementsByClassName('c');

需要注意的是,querySelectorAll 所接收的参数是必须严格符合 CSS 选择符规范的。所以下面这种写法,将会抛出异常。代码如下 [4]:

try {
var e1 = document.getElementsByClassName('1a2b3c');
var e2 = document.querySelectorAll('.1a2b3c');
} catch (e) {
console.error(e.message);
}
console.log(e1 && e1[0].className);
console.log(e2 && e2[0].className);

(CSS 选择器中的元素名,类和 ID 均不能以数字为开头。) 4. 返回值
大部分人都知道,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 对象 。
[1] Selectors API Level 2
[2] Document Object Model Core
[3] http://jsbin.com/cuduyigi/1/edit?html,js,console
[4] http://jsbin.com/mabefihi/1/watch?html,js,console
[5] 
Demo 1: http://jsbin.com/daduziba/1/watch?html,js,output
Demo 2: http://jsbin.com/xuvodipo/1/watch?html,js,output
[6] Selectors API Level 2
[7] Document Object Model Core
[8] Document Object Model HTML
[9] http://jsbin.com/qijivove/1/watch?html,js,console

document.getElementById动态的Node集合随时变化, 和document.querySelector静态的后续无法变化的更多相关文章

  1. document.getElementById和document.querySelector的区别

    zepto中的$(".111")出错,jQuery中$(".111")不出错的原因: zepto用document.querySelector实现,jQuery ...

  2. document.getElementById()使用方法

    document.getElementById使用 语法:oElement = document .getElementById ( sID ) 參数:sID――必选项. 字符串 (String) . ...

  3. 在JAVASCRIPT中,为什么document.getElementById不可以再全局(函数外)使用?

    今天在使用JavaScript使用document.ElementById("ID")的时候,发现var x = document.getElementById("chi ...

  4. document.getElementById()与 $()区别

    document.getElementById()返回的是DOM对象,而$()返回的是jQuery对象 什么是jQuery对象? ---就是通过jQuery包装DOM对象后产生的对象.jQuery对象 ...

  5. jquery中的$("#id")与document.getElementById("id")的区别

    以前一直认为jquery中的$("#id")和document.getElementByIdx_x("id")得到的效果是一样的,今天做特效的时候才发现并不是这 ...

  6. document.getElementById 和 document.getElementsByClassName获取DOM元素的区别

    想必小伙伴们对于 JS 获取DOM的几种方法早已烂熟于心,了然于胸,   尤其是 document.getElementById 和 document.getElementsByClassName, ...

  7. document.write vs document.getElementById

    document.write: JavaScript中对document.open所开启的文档流(document stream操作的API方法,它能够直接在文档流中写入字符串,一旦文档流已经关闭,那 ...

  8. document.getElementsByName和document.getElementById用法

    本文的问题在国外的一个网站得到了答案http://stackoverflow.com/questions/11235409/no-getelementbyid-for-body document.bo ...

  9. JS函数动作分层结构详解及Document.getElementById 释义 js及cs数据类型区别 事件 函数 变量 script标签 var function

    html +css 静态页面 js     动态 交互   原理: js就是修改样式, 比如弹出一个对话框. 弹出的过程就是这个框由disable 变成display:enable. 又或者当鼠标指向 ...

随机推荐

  1. Spark SQL 编程初级实践

    一.实验目的 (1)       通过实验掌握 Spark SQL 的基本编程方法: (2)       熟悉 RDD 到 DataFrame 的转化方法: (3)       熟悉利用 Spark ...

  2. python之进程,线程,协程简单理解

    进程:资源单位,由操作系统控制调度.正在执行的一个程序或者过程,进程之间不共享资源,进程间通讯手段:管道,队列,信号量等.多用于计算密集型场景,如金融计算 线程:是cpu的最小执行单位,由操作系统控制 ...

  3. 关于网站的一些js和css常见问题的记录

    1. 文字超过宽度,给这个后面超过的文字用...来表示  white-space: nowrap;

  4. python安装画图模块pillow

    步骤一: install pillow (注意导入是 import PIL )       步骤二:如果pycharm中import选择不到,则需要在settings中导入下             ...

  5. PHP fwrite 函数:将字符串写入文件(追加与换行)

    PHP fwrite() fwrite() 函数用于向文件写入字符串,成功返回写入的字符数,否则返回 FALSE . 语法: int fwrite( resource handle, string s ...

  6. Spring AOP capabilities and goals

    Spring AOP 是用纯JAVA 实现的. 不需借助JAVA代码在编译处理阶段来实现. Spring 是在运行期实现的.AOP的实现可以在编译,加载,运行三个阶段来实现:Spring AOP 也不 ...

  7. Linux环境上部署Flask

    [该文章只涉及个人部署的简单流程,读者可通过其它途径了解详细部署流程] 依个人部署项目可预先安装好需要的环境,这里已提前安装好LNMP环境 1.安装Python环境 安装virtualenv环境 配置 ...

  8. noVNC支持手机自带键盘输入

    代码修改说明 novnc的web链接类似为:http://192.168.1.177:6080/vnc_auto.html?token=105356fa-bbe3-43e4-a0ce-7703dc42 ...

  9. 基于Zookeeper实现多进程分布式锁

    一.zookeeper简介及基本操作 Zookeeper 并不是用来专门存储数据的,它的作用主要是用来维护和监控你存储的数据的状态变化.当对目录节点监控状态打开时,一旦目录节点的状态发生变化,Watc ...

  10. shell脚本的一些常用操作

    字符串长度: ${#string}可获取string字符串的长度,如下: jenkins@soft1pc:~$ str="who are you"jenkins@soft1pc:~ ...