其实这两种方法的区别就是获取动态集合和静态集合的关系。 getElementById()(getXXXByXX)获取动态集合:通过函数获取元素之后,元素之后的改变还是会动态添加到已经获取的这个元素中。换句话说,通过这个方法获取到元素存储到变量的时候,以后每一次在Javascript函数中使用这个变量的时候都会再去访问一下这个变量对应的html元素。 querySelector()获取静态集合:通过函数获取元素之后,元素之后的改变并不会影响之前获取后存储到的变量。也就是获取到元素之后就和html中的这个元素没有关系

<!DOCTYPE html>
    <title>querySelector()和getElementById()的区别</title>
</head>
    <ul id="testUl">
        <li>1</li>
        <li>2</li>
        <li>3</li>
    <script type="text/javascript">
        var testUl = document.getElementsByTagName('ul')[0];
        var liList = testUl.getElementsByTagName('li');
        for (var i = 0; i < liList.length; i++) {
            console.log(liList.length);
            /** 向ul中追加li标签 */
            testUl.appendChild(document.createElement('li'));
    </script>
</body>
</html>

使用这个方法实现的时候,程序会形成一个死循环。原因是在for循环中每次执行完毕后会判断 i 和 liList.length 的关系,之前说到,每一次使用 liList 这个变量的时候会再去访问一下对应的html元素,但通过for循环中的语句,每次执行一遍后liList会增加一个元素,这就导致liList.length一直增加,从而不会到达循环的结束条件,形成死循环。 同样的代码将JavaScript中的处理语句替换成下面的语句:

<script type="text/javascript">
    var testUl = document.querySelector('ul');
    var liList = testUl.querySelectorAll('li');
    for (var i = 0; i < liList.length; i++) {
        console.log(liList.length);
        /** 向ul中追加li标签 */
        testUl.appendChild(document.createElement('li'));
</script>

这就说明了一个问题:获取到元素之后,只要我不重新使用语句再次获取这个元素,之前的变量就一直不会改变,也就是说,通过querySelector(querySelectorAll)获取到元素之后,不论html元素再怎么改变,这个变量并不会随之发生改变,这个变量已经和html元素没有任何关系了。

这就是JavaScript中querySelector()和getElementById()(getXXXByXX)的区别,虽然大部分时间两者可以互换,但是最好在使用的过程中先斟酌一下是否可以使用其中的某一个,避免出现死循环导致程序都关不了。