querySelector ve querySelectorAll vs getElementsByClassName ve getElementById JavaScript'te


165

Tam arasındaki fark nedir bilmek istiyorum querySelectorve querySelectorAllkarşı getElementsByClassNameve getElementById?

Gönderen bu bağlantı Ben o toplayabilir querySelectoryazabilirim document.querySelector(".myclass")sınıfla öğeleri almak için myclassve document.querySelector("#myid")kimliğine sahip eleman almak için myid. Ama bunu zaten yapabilirim getElementsByClassNameve getElementById. Hangisi tercih edilmeli?

Ayrıca ID'nin dinamik olarak iki nokta üst üste ile oluşturulduğu ve bunun gibi göründüğü XPages'de çalışıyorum view:_id1:inputText1. Yani yazdığımda document.querySelector("#view:_id1:inputText1")işe yaramıyor. Ama yazma document.getElementById("view:_id1:inputText1")işleri. Neden herhangi bir fikir?


1
querySelector, html öğesi ve özniteliklerini sorgulamak için anahtar öğeler olarak içerebilen bir HTML DOM ağacını sorgulamak için kullanılır ... bunu elde etmek için normal ifadeyi kullanabilirsiniz .. dojo.query () aynı şeyi yapar
anix

1
Bunu mu demek istediniz document.querySelectorAll(".myclass")? Kullanıldığında document.querySelector(".myclass")yalnızca eşleşen ilk öğe döndürülür.
17'de

Yanıtlar:


113

SorguSelector ve querySelectorAll arasındaki getElementsByClassName ve getElementById arasındaki farkın tam olarak ne olduğunu bilmek ister misiniz?

Sözdizimi ve tarayıcı desteği.

querySelector daha karmaşık seçiciler kullanmak istediğinizde daha kullanışlıdır.

ör. Tüm liste öğeleri, foo sınıfının bir üyesi olan bir öğeden alınmıştır: .foo li

document.querySelector ("# view: _id1: inputText1") çalışmıyor. Ancak document.getElementById ("view: _id1: inputText1") yazmak işe yarar. Neden herhangi bir fikir?

:Karakteri bir seçicinin içindeki özel bir anlamı vardır. Kaçmak zorundasın. (Eğer kaçmak zorunda seçici kaçış karakteri de bir JS dizede özel bir anlamı vardır o da).

document.querySelector("#view\\:_id1\\:inputText1")

3
Tarayıcıdan tarayıcıya (ve sürümden sürüme) değişecektir. Seçici tabanlı olanların daha pahalı olduğunu varsayıyorum (ancak önemli olacak bir şekilde değil)
Quentin

1
@ Janaspage'in ifadesini destekliyorum. Site bugün de kapalı.
doplumi

6
Ve sınıf seçimi hakkında ayrıca bkz . Jsperf.com/getelementsbyclassname-vs-queryselectorall/25 . Sonuç: Bir çok daha saf jquery daha javascript ve belirli fonksiyonları tercih etmeliyiz getElementByIdve getElementsByClassName. ClassName seçimi, olmadan yüzlerce kez daha yavaş olabilir getElementsByClassName.
Atrahasis

101

Mozilla Dokümanlarından toplama :

NodeSelector arabirimi Bu belirtim, Document, DocumentFragment veya Element arabirimlerini uygulayan nesnelere iki yeni yöntem ekler:

querySelector

Düğümün alt ağacındaki ilk eşleşen Öğe düğümünü döndürür . Eşleşen düğüm bulunamazsa null değeri döndürülür.

querySelectorAll

Düğümün alt ağacındaki eşleşen tüm Öğe düğümlerini veya eşleşme bulunamazsa boş bir Düğüm Listesi döndürür .

ve

Not: Tarafından döndürülen NodeList querySelectorAll()yayında değil, yani DOM'daki değişiklikler koleksiyona yansıtılmıyor. Bu, canlı düğüm listeleri döndüren diğer DOM sorgulama yöntemlerinden farklıdır.


32
Canlı düğüm listesi ayrımına işaret etmek için +1. Sonuçları nasıl kullanmayı planladığınıza bağlı olarak farkında olmak son derece önemli bir farktır.
jmbpiano

7
"live", DOM çalışma zamanında eklenen düğüm anlamına gelir ve bu
newley

83

Farklılıklar hakkında, querySelectorAllve arasındaki sonuçlarda önemli bir tane vardır getElementsByClassName: dönüş değeri farklıdır. querySelectorAllstatik bir koleksiyon getElementsByClassNamedöndürürken, canlı bir koleksiyon döndürür. Sonuçları daha sonra kullanmak üzere bir değişkende depolarsanız bu karışıklığa neden olabilir:

  • İle oluşturulan bir değişken , yöntemin çağrıldığı andaquerySelectorAll seçiciyi yerine getiren öğeleri içerecektir .
  • İle oluşturulan bir değişken getElementsByClassName, seçiciyi kullanıldığında yerine getiren öğeleri içerir (bu, yöntemin çağrıldığı andan farklı olabilir).

Eğer değişkenler yeniden olsanız bile Örneğin, ihbar nasıl aux1ve aux2bunlar sınıfları güncelledikten sonra farklı değerlerini içerir:

// storing all the elements with class "blue" using the two methods
var aux1 = document.querySelectorAll(".blue");
var aux2 = document.getElementsByClassName("blue");

// write the number of elements in each array (values match)
console.log("Number of elements with querySelectorAll = " + aux1.length);
console.log("Number of elements with getElementsByClassName = " + aux2.length);

// change one element's class to "blue"
document.getElementById("div1").className = "blue";

// write the number of elements in each array (values differ)
console.log("Number of elements with querySelectorAll = " + aux1.length);
console.log("Number of elements with getElementsByClassName = " + aux2.length);
.red { color:red; }
.green { color:green; }
.blue { color:blue; }
<div id="div0" class="blue">Blue</div>
<div id="div1" class="red">Red</div>
<div id="div2" class="green">Green</div>


2
Sadece söz - bütün büyük DOM apis yani bir düğüm listesi dönen document.getElementsByName, document.getElementsByTagNameNSya da document.getElementsByTagNameaynı davranışı sergiler.
RBT

2
Bazı analizler querySelector'un getElementById'den daha fazla zaman aldığını söylüyor, burada olduğu gibi dimlucas.com/index.php/2016/09/17/… . Erişim zamanını dikkate alırsak ne olur? GetElementById'den alınan canlı düğüm, querySelector'daki statik düğümden daha fazla zaman alıyor mu?
Eric

1
@RBT Bu eski DOM API'lerinin NodeList nesnelerini döndürmediğini, HTMLCollections döndürdüğünü söyleyebilirim.
Miscreant

@Eric document.getElementById(), canlı bir düğüm döndürmez. document.querySelector('#id_here')Muhtemelen daha hızlıdır, çünkü querySelectorönce CSS seçiciyi ayrıştırmak zorunda kalacaktır.
Miscreant

68

Bu yanıt için, bkz querySelectorve querySelectorAll* ve querySelector olarak getElementById, getElementsByClassName, getElementsByTagName, ve getElementsByNamegetElement olarak *.

Temel Farklılıklar

  1. 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.
  2. 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.
  3. 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.
  4. 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.


4
Bu konuda açık ara en doğru cevap. Daha fazla oy verilmeli.
SeaWarrior404

blogunuza koymak gerekir, Sasha
theking2

25

Bu sayfaya performans açısından kullanmak için daha iyi bir yöntem bulmak için geldim - yani daha hızlı:

querySelector / querySelectorAll or getElementsByClassName

ve bunu buldum: https://jsperf.com/getelementsbyclassname-vs-queryselectorall/18

Yukarıdaki 2 x örnek üzerinde bir test yapar, ayrıca jQuery'nin eşdeğer seçicisinde de bir test yapar. test sonuçlarım şöyleydi:

getElementsByClassName = 1,138,018 operations / sec - <<< clear winner
querySelectorAll = 39,033 operations / sec
jquery select = 381,648 operations / sec

1
Vay canına, bu büyük bir fark, baktığın için teşekkürler. Açıkça querySelectorAllsahnelerin arkasında (seçici ifadenin ayrıştırılması, sözde öğelerin muhasebeleştirilmesi, vb. Dahil) ilave çalışmalara ihtiyaç duyulurken getElementsByClassName, yalnızca özyinelemeli bir nesne geçişidir.
John Weisz

18

querySelector kimlikleri ve sınıfları ve sözde sınıfları birlikte içeren tam bir CSS (3) -Selector olabilir:

'#id.class:pseudo'

// or

'tag #id .class .class.class'

ile getElementByClassNamesadece bir sınıf tanımlayabilirsiniz

'class'

ile getElementByIdsadece bir kimlik tanımlayabilirsiniz

'id'

1
:firstbir CSS seçici şimdi? :first-class, ya da :first-of-typebelki, ama ben :firstbir JavaScript / jQuery / Sizzle ek olduğunu düşündüm .
David, Monica

@DavidThomas Evet, CSS3'ün bir parçası. Bu şekilde kullanılabilir: css-tricks.com/almanac/selectors/f/first-child
algoritma

2
ama :firstfark edilir bir şekilde değil :first-child.
David, Monica

3
"Yazarlara, seçicilerde sözde öğelerin kullanılmasına izin verilirken, belgedeki hiçbir öğeyle eşleşmeyecekleri ve böylece herhangi bir öğenin döndürülmeyecekleri önerilir. Bu nedenle, yazarlara sözde öğelerin kullanılmasından kaçınmaları önerilir. bu spesifikasyonda tanımlanan yöntemlere geçirilen seçicilerdeki öğeler. " w3.org/TR/selectors-api/#grammar
zengin remer

Ayrıca, IE'de (tabii ki) sözde öğeleri seçerken boş bir öğe listesi yerine kök html öğesini döndürmesine neden olan bir hata var.
zengin hatırlatıcı

7

querySelectorve querySelectorAllnispeten yeni bir API'lardır, oysa getElementByIdve getElementsByClassNameçok daha uzun süredir bizimle birlikte. Bu, kullandığınız şeyin çoğunlukla desteklemeniz gereken tarayıcılara bağlı olacağı anlamına gelir.

Gelince :, özel bir anlamı vardır, bu yüzden bir kimlik / sınıf adının bir parçası olarak kullanmak zorundaysanız kaçmak zorundasınız.


13
Bu mutlaka doğru değildir. Örneğin, querySelectorAllIE8'de kullanılabilir, ancak getElementsByClassNamemevcut değildir.
DaveJ

querySelectorAll... temelde her şey: caniuse.com/#search=querySelectorAll
dsdsdsdsd


5

querySelectorw3c Seçici API'sı

getElementByw3c DOM API'sı

IMO'nun en dikkat çekici farkı, dönüş türünün querySelectorAllstatik bir düğüm listesi olması ve getElementsBybunun canlı bir düğüm listesidir. Bu nedenle demo 2'deki döngü asla sona ermez, çünkü liscanlıdır ve her yineleme sırasında kendini günceller.

// Demo 1 correct
var ul = document.querySelectorAll('ul')[0],
    lis = ul.querySelectorAll("li");
for(var i = 0; i < lis.length ; i++){
    ul.appendChild(document.createElement("li"));
}

// Demo 2 wrong
var ul = document.getElementsByTagName('ul')[0], 
    lis = ul.getElementsByTagName("li"); 
for(var i = 0; i < lis.length ; i++){
    ul.appendChild(document.createElement("li")); 
}

4

"QuerySelector" ve "querySelectorAll" arasındaki fark

//querySelector returns single element
let listsingle = document.querySelector('li');
console.log(listsingle);


//querySelectorAll returns lit/array of elements
let list = document.querySelectorAll('li');
console.log(list);


//Note : output will be visible in Console
<ul>
<li class="test">ffff</li>
<li class="test">vvvv</li>
<li>dddd</li>
<li class="test">ddff</li>
</ul>


2

şuna bak

https://codepen.io/bagdaulet/pen/bzdKjL

% 25 üzerinde getElementById sorgudan en hızlıSelector

jquery en yavaş

var q = time_my_script(function() {

    for (i = 0; i < 1000000; i++) {
         var w = document.querySelector('#ll');
    }

});

console.log('querySelector: '+q+'ms');

-3

QuerySelector ve getlementbyID (Claassname, Tagname vb.) Arasındaki temel fark, querySelector öğesinin yalnızca bir çıktı döndürürken, getElementBy * tüm öğeleri döndürür.

Daha açık hale getirmek için bir örnek ele alalım.

 <nav id="primary" class="menu">
                            <a class="link" href="#">For Business</a>
                            <a class="link" href="#">Become an Instructor</a>
                            <a class="link" href="#">Mobile Applications</a>
                            <a class="link" href="#">Support</a>
                            <a class="link" href="#">Help</a>
   </nav> 

Aşağıdaki kod farkı açıklayacaktır

**QUERY SELECTOR**
document.querySelector('.link'); // Output : For Business (element)

document.querySelectorAll('.link'); //Out All the element with class link

**GET ELEMENT**
document.getElementsByClassName('link') // Output : will return all the element with a class "link" but whereas in query selector it will return only one element which encounters first.

Queryslector için go tek öğe seçmek istiyorsak veya getElement için birden fazla öğe gitmek istiyorsak


1
getElementById yalnızca bir öğe döndürür, bu ikisi arasında bir fark değildir.
Timofey 'Sasha' Kondrashov
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.