QuerySelector/QuerySelectorAll和getElementById/getElementsByClassName的區別

莫珂發表於2018-02-09

在React、Vue框架流行的今天,操作DOM這種方式已經用的比較少了,不過工作中有時候還是會用到的。今天就來說一下QS/QSA和GEBI/GEBC(這裡為了方便偷個懶使用了縮寫)的區別。

1. 相容性:

getElementById

getElementsByClassName

querySelector/querySelectorAll

上圖是我從大名鼎鼎的Can I Use上截的圖,可以看到各個瀏覽器對於這幾種的支援情況。

結論:

如果你不考慮相容特定版本的瀏覽器,這一點你可以忽略。

2. 效率:

首先我們來比較 GEBI和QS 的差別,建立測試檔案如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <div id="test"></div>
    <script>
        console.time('querySelector');
        for (var i = 0; i < 100000; i++) {
            document.querySelector("#test");
        }
        console.timeEnd('querySelector');

        console.time('getElementById');
        for (var i = 0; i < 100000; i++) {
            document.getElementById("test");
        }
        console.timeEnd('getElementById');

    </script>
</body>
</html>
複製程式碼

GEBI和QS比較

我們再建立一個測試檔案來比較GEBC和QSA,如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <div class="test"></div>
    <div class="test"></div>
    <div class="test"></div>
    <script>
        console.time('querySelectorAll');
        for (var i = 0; i < 10000; i++) {
          document.querySelectorAll(".test");
        }
        console.timeEnd('querySelectorAll');
        
        console.time('getElementsByClassName');
        for (var i = 0; i < 10000; i++) {
          document.getElementsByClassName("test");
        }
        console.timeEnd('getElementsByClassName');

    </script>
</body>
</html>
複製程式碼

GEBC/QSA

結論:

總的來說QS和QSA要比GEBI和GEBC要慢。

有人要問了,這QS和QSA不是後來提出來的嗎?為什麼效率這麼低還要用?不要著急,接下來我們就要講到了。

靈活性:

QS/QSA 均支援CSS的選擇器,也就是說你可以這麼寫:

querySelector('div img .test')
//找到div下面的img下面類名為test的元素
複製程式碼

怎麼樣?GEBI和GEBC做不到吧,他們只能選擇固定id或者固定類名,在這一點上QS/QSA差距還是挺大的(QS/QSA 不能使用偽類選擇器)。

結論:

  1. QS/QSA相較於GEBI/GEBC更加靈活和方便
  2. QS/QSA對於CSS偽類選擇器不生效,具體見mdn querySelector

動態性:

接下來我們來討論QSA與GEBC最大的區別動態性。不知道我在說什麼?沒關係繼續往下看吧。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <script>
        a = document.querySelectorAll('img')
        b = document.getElementsByTagName('img')
        document.body.appendChild(new Image())
        console.log(a.length) // 0
        console.log(b.length) // 1
    </script>
</body>
</html>
複製程式碼

結論:

通過QSA選擇的不受後來DOM變化的影響,但是通過GEBC會受DOM的影響。

總結:

QS/QSA 給我們提供了極大的靈活性和便利性,但效能相較GEBI/GEBC有一定差距,並且相容性上存在一定差距。再不引入第三方庫如jQuery的情況下,使用哪種要根據具體需求來定,找到最優的解決方案即可。

相關文章