Untuk jawaban ini, saya lihat querySelectordan querySelectorAllsebagai querySelector * dan getElementById, getElementsByClassName, getElementsByTagName, dan getElementsByNamesebagai getElement *.
Perbedaan utama
- querySelector * lebih fleksibel, karena Anda dapat memberikannya pemilih CSS3 apa pun, bukan hanya yang sederhana untuk id, tag, atau kelas.
- Kinerja querySelector berubah dengan ukuran DOM yang digunakan. * Untuk lebih tepatnya, panggilan querySelector * dijalankan dalam waktu O (n) dan getElement * panggilan dijalankan dalam waktu O (1), di mana n adalah jumlah total semua anak dari elemen atau dokumen yang dipanggil. Fakta ini tampaknya yang paling tidak terkenal, jadi saya berani.
- panggilan getElement * mengembalikan referensi langsung ke DOM, sedangkan querySelector * secara internal membuat salinan dari elemen yang dipilih sebelum mengembalikan referensi kepada mereka. Ini disebut sebagai elemen "hidup" dan "statis". Ini TIDAK sepenuhnya terkait dengan jenis yang mereka kembalikan. Tidak ada cara saya tahu untuk mengetahui apakah suatu elemen hidup atau statis secara terprogram, karena tergantung pada apakah elemen itu disalin pada beberapa titik, dan bukan merupakan properti intrinsik dari data. Perubahan ke elemen langsung langsung diterapkan - mengubah elemen langsung mengubahnya langsung di DOM, dan oleh karena itu baris JS berikutnya dapat melihat perubahan itu, dan menyebar ke elemen langsung lainnya yang mereferensikan elemen tersebut dengan segera. Perubahan pada elemen statis hanya ditulis kembali ke DOM setelah skrip saat ini selesai dijalankan.
- Jenis pengembalian panggilan ini bervariasi.
querySelectordan getElementByIdkeduanya mengembalikan elemen tunggal. querySelectorAlldan getElementsByNamekeduanya mengembalikan NodeLists, menjadi fungsi yang lebih baru yang ditambahkan setelah HTMLCollection keluar dari mode. Yang lebih tua getElementsByClassNamedan getElementsByTagNamekeduanya mengembalikan HTMLCollections. Sekali lagi, ini pada dasarnya tidak relevan dengan apakah unsur-unsurnya hidup atau statis.
Konsep-konsep ini dirangkum dalam tabel berikut.
Function | Live? | Type | Time Complexity
querySelector | N | Element | O(n)
querySelectorAll | N | NodeList | O(n)
getElementById | Y | Element | O(1)
getElementsByClassName | Y | HTMLCollection | O(1)
getElementsByTagName | Y | HTMLCollection | O(1)
getElementsByName | Y | NodeList | O(1)
Detail, Tip, dan Contoh
HTMLCollections tidak seperti array seperti NodeLists dan tidak mendukung .forEach (). Saya menemukan operator spread berguna untuk mengatasi ini:
[...document.getElementsByClassName("someClass")].forEach()
Setiap elemen, dan global document, memiliki akses ke semua fungsi ini kecuali untuk getElementByIddan getElementsByName, yang hanya diimplementasikan pada document.
Memanggil panggilan getElement * alih-alih menggunakan querySelector * akan meningkatkan kinerja, terutama pada DOM yang sangat besar. Bahkan pada DOM kecil dan / atau dengan rantai yang sangat panjang, umumnya lebih cepat. Namun, kecuali Anda tahu Anda membutuhkan kinerja, keterbacaan kueriSelektor * harus lebih disukai. querySelectorAllseringkali lebih sulit untuk ditulis ulang, karena Anda harus memilih elemen dari NodeList atau HTMLCollection di setiap langkah. Misalnya, kode berikut ini tidak berfungsi:
document.getElementsByClassName("someClass").getElementsByTagName("div")
because you can only use getElements* on single elements, not collections. For example:
`document.querySelector("#someId .someClass div")`
could be written as:
document.getElementById("someId").getElementsByClassName("someClass")[0].getElementsByTagName("div")[0]
Note the use of `[0]` to get just the first element of the collection at each step that returns a collection, resulting in one element at the end just like with `querySelector`.
Karena semua elemen memiliki akses ke panggilan querySelector * dan getElement *, Anda dapat membuat rantai menggunakan kedua panggilan, yang dapat berguna jika Anda menginginkan beberapa peningkatan kinerja, tetapi tidak dapat menghindari querySelector yang tidak dapat ditulis dalam hal panggilan getElement * .
Meskipun umumnya mudah untuk mengetahui apakah pemilih dapat ditulis hanya menggunakan panggilan getElement *, ada satu kasus yang mungkin tidak jelas:
document.querySelectorAll(".class1.class2")
dapat ditulis ulang sebagai
document.getElementsByClassName("class1 class2")
Menggunakan getElement * pada elemen statis yang diambil dengan querySelector * akan menghasilkan elemen yang hidup sehubungan dengan subset statis DOM yang disalin oleh querySelector, tetapi tidak hidup sehubungan dengan dokumen lengkap DOM ... ini adalah tempat sederhana interpretasi langsung / statis elemen mulai berantakan. Anda mungkin harus menghindari situasi di mana Anda harus khawatir tentang hal ini, tetapi jika Anda melakukannya, ingat bahwa querySelector * memanggil elemen copy yang mereka temukan sebelum mengembalikan referensi kepada mereka, tetapi panggilan getElement * mengambil referensi langsung tanpa menyalin.
Baik API menentukan elemen mana yang harus dipilih terlebih dahulu jika ada beberapa kecocokan.
Karena querySelector * berulang melalui DOM sampai menemukan kecocokan (lihat Perbedaan Utama # 2), hal di atas juga menyiratkan bahwa Anda tidak dapat mengandalkan posisi elemen yang Anda cari di DOM untuk memastikan bahwa itu ditemukan dengan cepat - the browser dapat beralih melalui DOM mundur, maju, mendalam pertama, luasnya pertama, atau sebaliknya. getElement * masih akan menemukan elemen dalam jumlah waktu yang kira-kira sama terlepas dari penempatannya.