感谢 http://www.zhihu.com/question/24702250 简生 的回答

1. W3C 标准

querySelectorAll 属于 W3C 中的 Selectors API 规范。而 getElementsBy 系列则属于 W3C 的 DOM 规范

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。代码如下

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

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

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);

4. 返回值

大部分人都知道,querySelectorAll 返回的是一个 Static Node List,而 getElementsBy 系列的返回的是一个 Live Node List。

看看下面这个经典的例子 dome1 dome2

// 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 方法有明确规定

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

那什么是 NodeList 呢?

W3C 中是这样说明的

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 的定义如下:

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 规范。

这样说有点难理解,看看下面的例子会比较好理解 dome

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 对象 。

querySelectorAll 方法相比 getElementsBy 系列方法有什么区别的更多相关文章

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

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

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

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

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

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

  4. querySelectorAll 方法和 getElementsBy 系列方法的区别

    本文是我在知乎上的一个回答:http://www.zhihu.com/question/24702250/answer/28695133 ————— 下面是正文 ————— 1. W3C 标准quer ...

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

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

  6. querySelector.. 方法相比 getElementsBy..

    querySelectorAll 返回的是一个 Static Node List,而 getElementsBy 系列的返回的是一个 Live Node List. 看看下面这个经典的例子 [5]: ...

  7. ReactiveSwift源码解析(九) SignalProducerProtocol延展中的Start、Lift系列方法的代码实现

    上篇博客我们聊完SignalProducer结构体的基本实现后,我们接下来就聊一下SignalProducerProtocol延展中的start和lift系列方法.SignalProducer结构体的 ...

  8. xorm -sum 系列方法实例

    求和数据可以使用Sum, SumInt, Sums 和 SumsInt 四个方法,Sums系列方法的参数为struct的指针并且成为查询条件. package main import ( " ...

  9. querySelectorAll和getElementsBy 系列比较

    querySelectorAll 相比下面这些方法有什么区别? (1)getElementsByTagName (2)getElementsByClassName (3)getElementsByNa ...

随机推荐

  1. Candy Bags

    读懂了题就会发现这是个超级大水题 Description Gerald has n younger brothers and their number happens to be even. One ...

  2. 不规则三角网 Delaunay——TIN

    http://blog.csdn.net/u010025211/article/details/25032209 知识点一:平面中判断一个点是否在三角形内部. #include <stdio.h ...

  3. 解决在IE浏览器下 boder边框出现断裂或虚线的问题

    ie6.0下面经常会出现border边框断断续续的问题,等深一步了解了div之后自然会经常碰到这种问题了,不过初学div+css 的一般不会用遇到这个问题,因为初学者不会偷懒,等我们觉得用的很熟了,各 ...

  4. android.view.InflateException: Binary XML file line #7: Error inflating class(OOM)

    由于页面含有ImageView引起的内存溢出. 作如下处理:在OnDestroy中 Drawable d = imageView.getDrawable(); if (d != null) d.set ...

  5. Raknet实现的简单服务器与客户端的交互

    1. 首先下载Raknet的源代码,我用的是4.0的,不是最新的,解压后编译DLL工程,编译完成后进入解压的根目录下,进入Lib文件夹下找到RakNet_DLL_Debug_Win32.dll,  R ...

  6. 在Win8上安装pyinstaller打包python成为可执行文件

    首先我使用的电脑系统是: Windows-8-6.2.9200 Python的版本是: 2.7.8 默认已安装python2.7且设置好了环境变量. 仅为个人记录,非教程. 首先先安装pip: 首先先 ...

  7. 2^x mod n = 1(hd1395)

    2^x mod n = 1 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Tot ...

  8. A Simple Task

    A Simple Task Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Tot ...

  9. Windows下Node.js开发环境搭建

    1.http://nodejs.org/下载node.js运行环境安装 2.打开DOS命令行 .安装express框架 1 >npm install express 末尾显示如下为安装成功 .安 ...

  10. 时间TDateTime相当于是Double,即双精度数64位,终于查到它用11位表示e,53位表示精度(整数小数一起),最前面一位表示正负

    http://docwiki.embarcadero.com/RADStudio/Seattle/en/Internal_Data_Formats 关于Double的RTL函数,好像就一个:TrySt ...