先看问题


<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .red {
            color: red;
        }

        .green {
            color: green;
        }
    </style>
</head>
<body>

<ul>
    <li class="red">哈哈0</li>
    <li class="red">哈哈1</li>
    <li class="red">哈哈2</li>
    <li class="red">哈哈3</li>
    <li class="red">哈哈4</li>
</ul>

<script>
    var liArr = document.getElementsByClassName('red');//一绿一红
    //    var liArr = document.querySelectorAll('.red');//全绿

    for (var i = 0; i < liArr.length; i++) {
        liArr[i].className = 'green';
    }
</script>
</body>
</html>

效果

DOM同步.png

解释

querySelectorAll 会把所有li都改成红色, 但用 getElementsByClassName 只会改变一半li的颜色.

这是因为 querySelectorAll 返回的是一个 Static Node List, 每次操作之后liArr本身不会改变. 而 getElementsBy 系列的返回的是一个 Live Node List ,每次操作都会实时更新liArr, i++之后就呈现出跳跃的效果了 .

注意事项:

1) querySelectorAll 里要求严格符合CSS规范.

CSS 选择器中的元素名,类和 ID 均不能以数字为开头,下面这种写法将会抛出异常.

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


getElementById可以接受一个不合法的id,比如

<div id="my.name"></div>

用document.querySelectorAll(‘#my.name’)是query不到它的,

但是用 document.getElementById(‘my.name’)却可以.

2) 查找范围.

querySelectorAll 的查找范围是整个文档.

<div id="test1"><p>test</p></div>
var a = document.getElementById("test1");

a.querySelectorAll("div p").length; // 1
a.getElementsByTagName("div p").length; // 0

a.querySelectorAll("#test1 p").length; // 1
a.getElementsByTagName("#test1 p").length; // 0

a.querySelectorAll("html #test1 p").length; // 1
a.getElementsByTagName("html #test1 p").length; // 0

参考

https://www.zhihu.com/question/24702250