Bu yanıt için, bkz querySelectorve querySelectorAll* ve querySelector olarak getElementById, getElementsByClassName, getElementsByTagName, ve getElementsByNamegetElement olarak *.
Temel Farklılıklar
- querySelector *, yalnızca id, tag veya sınıf için basit olanları değil, herhangi bir CSS3 seçicisini iletebileceğiniz için daha esnektir.
- QuerySelector'ın performansı, çağrıldığı DOM'nin boyutuna göre değişir.* Kesin olarak, querySelector * çağrıları O (n) zamanında ve getElement * çağrıları O (1) zamanında çalışır; burada n, çağrıldığı öğenin veya belgenin tüm alt öğelerinin toplam sayısıdır. Bu gerçek en az bilinen gibi görünüyor, bu yüzden cesurca yaşıyorum.
- getElement * çağrıları DOM'a doğrudan referanslar döndürürken, querySelector * dahili olarak seçilen öğelerin referanslarını döndürmeden önce kopyalarını oluşturur. Bunlara "canlı" ve "statik" elemanlar denir. Bu kesinlikle geri döndükleri türlerle ilgili DEĞİLDİR. Öğenin bir noktada kopyalanıp kopyalanmadığına ve verilerin gerçek bir özelliği olmadığına bağlı olarak, bir öğenin programlı olarak canlı veya statik olup olmadığını anlamanın hiçbir yolu yoktur. Canlı öğelerde yapılan değişiklikler hemen uygulanır - canlı öğeyi değiştirmek doğrudan DOM'da değişir ve bu nedenle JS'nin bir sonraki satırı bu değişikliği görebilir ve bu öğeye hemen başvuran diğer canlı öğelere yayılır. Statik öğelerde yapılan değişiklikler yalnızca geçerli komut dosyası yürütüldükten sonra DOM'ye geri yazılır.
- Bu çağrıların dönüş türleri değişiklik gösterir.
querySelectorve getElementByIdher ikisi de tek bir öğe döndürür. querySelectorAllve getElementsByNameher ikisi de HTMLCollection modası geçtikten sonra eklenen yeni işlevler olan Düğüm Listeleri döndürür. Daha eski getElementsByClassNameve getElementsByTagNameher ikisi de HTMLColeksiyonlarını döndürür. Yine, bu aslında öğelerin canlı mı yoksa statik mi olduğu ile ilgisizdir.
Bu kavramlar aşağıdaki tabloda özetlenmiştir.
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)
Ayrıntılar, İpuçları ve Örnekler
HTMLCollections, NodeLists gibi dizi benzeri değildir ve .forEach () öğesini desteklemez. Forma operatörü, bu soruna geçici bir çözüm bulmak için yararlı buluyorum:
[...document.getElementsByClassName("someClass")].forEach()
Her öğenin ve küresel olan, yalnızca üzerinde uygulanan ve documentdışındaki tüm bu işlevlere erişebilir .getElementByIdgetElementsByNamedocument
QuerySelector * kullanmak yerine getElement * çağrılarını zincirlemek, özellikle çok büyük DOM'larda performansı artıracaktır. Küçük DOM'larda ve / veya çok uzun zincirlerle bile, genellikle daha hızlıdır. Ancak, performansa ihtiyacınız olduğunu bilmiyorsanız, querySelector * öğesinin okunabilirliği tercih edilmelidir. querySelectorAllher adımda NodeList veya HTMLCollection öğelerinden seçim yapmanız gerektiğinden, yeniden yazmak genellikle daha zordur. Örneğin, aşağıdaki kod yok değil çalışır:
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`.
Tüm öğeler hem querySelector * hem de getElement * çağrılarına erişebildiğinden, her iki çağrıyı kullanarak zincirler oluşturabilirsiniz, bu da performans artışı istiyorsanız yararlı olabilir, ancak getElement * çağrıları açısından yazılamayan bir querySelector'dan kaçınamaz .
Bir seçicinin yalnızca getElement * çağrıları kullanılarak yazılabilir olup olmadığını söylemek genellikle kolay olsa da, belirgin olmayan bir durum vardır:
document.querySelectorAll(".class1.class2")
olarak yeniden yazılabilir
document.getElementsByClassName("class1 class2")
QuerySelector * ile getirilen statik bir öğede getElement * kullanılması, querySelector tarafından kopyalanan DOM'un statik alt kümesine göre canlı olan, ancak DOM belgesinin tamamına göre canlı olmayan bir öğeyle sonuçlanır. elementlerin canlı / statik yorumu parçalanmaya başlar. Muhtemelen bu konuda endişelenmeniz gereken durumlardan kaçınmalısınız, ancak bunu yaparsanız, querySelector * öğesinin referansları döndürmeden önce buldukları kopya öğelerini çağırdığını, ancak getElement * çağrılarının kopyalamadan doğrudan başvuruları aldığını unutmayın.
Her iki API da birden fazla eşleşme varsa önce hangi öğenin seçilmesi gerektiğini belirtmez.
QuerySelector *, bir eşleşme bulana kadar DOM'da yinelendiği için (bkz. Ana Fark # 2), yukarıda da hızlı bir şekilde bulunmasını garanti etmek için DOM'da aradığınız bir öğenin konumuna güvenemeyeceğiniz anlamına gelir - tarayıcı DOM'u geriye, ileri, önce derinlik, önce genişlik veya başka şekilde yineleyebilir. getElement * öğeleri, yerleşimlerine bakılmaksızın kabaca aynı sürede bulacaktır.