jQuery vs document.querySelectorAll

161

Ouvi várias vezes que o ativo mais forte do jQuery é a maneira como ele consulta e manipula elementos no DOM: você pode usar consultas CSS para criar consultas complexas que seriam muito difíceis de executar em javascript regular. No entanto, tanto quanto eu sei, você pode obter o mesmo resultado com document.querySelectorou document.querySelectorAll, que são suportados no Internet Explorer 8 e superior.

Portanto, a pergunta é a seguinte: por que 'arriscar' a sobrecarga do jQuery se seu ativo mais forte pode ser alcançado com JavaScript puro?

Eu sei que o jQuery tem mais do que apenas seletores CSS, por exemplo, AJAX entre navegadores, bom evento anexando etc. Mas sua parte de consulta é uma parte muito grande da força do jQuery!

Alguma ideia?

Joel_Blum
fonte
4
(1) A travessia / modificação do DOM é muito mais rápida e fácil com o jQuery. (2) Adiciona seus próprios seletores que não funcionarão nos querySelectormétodos. (3) Fazer chamadas AJAX é muito mais rápido e fácil com o jQuery. (4) Suporte no IE6 +. Tenho certeza de que há muitos outros pontos que também podem ser feitos.
21412 James Allardice
12
(5) ... o shorthand $ () para datilógrafos preguiçosos é obrigatório.
Dexter Huinda 16/07/2012
4
mais fácil sim, por que mais rápido? jQuery se traduz em javascript regular, tanto quanto eu sei ...
Joel_Blum
4
@ JamesAllardice - "toda essa bagunça" para XMLHttpRequest entre navegadores é talvez 30 linhas de código que você escreve uma vez e coloca em sua própria biblioteca.
21812 RobG #
6
@ RobG - Sim, eu não estou dizendo apenas use jQuery se é para isso que você está tentando usá-lo. É apenas um dos benefícios. Se você precisa de uma passagem fácil de DOM, AJAX e querySelectorAll, e precisa de tudo para trabalhar em navegadores mais antigos, o jQuery é uma escolha óbvia. Não estou dizendo que você deveria usá-lo assim .
11114 James Allardice

Respostas:

127

document.querySelectorAll() possui várias inconsistências nos navegadores e não é suportado em navegadores antigos. Isso provavelmente não causará mais problemas atualmente . Ele tem um mecanismo de escopo muito pouco intuitivo e alguns outros recursos não tão agradáveis . Além disso, com o javascript, é mais difícil trabalhar com os conjuntos de resultados dessas consultas, o que em muitos casos você pode querer fazer. jQuery fornece funções para trabalhar com eles como: filter(), find(), children(), parent(), map(), not()e vários outros. Sem mencionar a capacidade do jQuery de trabalhar com seletores de pseudo-classe.

No entanto, eu não consideraria essas coisas como os recursos mais fortes do jQuery, mas outras como "trabalhar" no dom (eventos, estilo, animação e manipulação) de maneira compatível com o navegador cruzado ou na interface ajax.

Se você deseja apenas o mecanismo seletor do jQuery, pode usar o que o próprio jQuery está usando: Sizzle Dessa forma, você tem o poder do mecanismo jQuerys Selector sem a sobrecarga desagradável.

Edição: Apenas para o registro, eu sou um grande fã de JavaScript baunilha. No entanto, é verdade que às vezes você precisa de 10 linhas de JavaScript, onde escreveria uma linha jQuery.

É claro que você precisa ser disciplinado para não escrever o jQuery assim:

$('ul.first').find('.foo').css('background-color', 'red').end().find('.bar').css('background-color', 'green').end();

Isso é extremamente difícil de ler, enquanto o último é bem claro:

$('ul.first')
   .find('.foo')
      .css('background-color', 'red')
.end()
   .find('.bar')
      .css('background-color', 'green')
.end();

O JavaScript equivalente seria muito mais complexo, ilustrado pelo pseudocódigo acima:

1) Encontre o elemento, considere pegar todo o elemento ou apenas o primeiro.

// $('ul.first')
// taking querySelectorAll has to be considered
var e = document.querySelector("ul.first");

2) Itere a matriz de nós filhos através de alguns loops (possivelmente aninhados ou recursivos) e verifique a classe (a lista de classes não está disponível em todos os navegadores!)

//.find('.foo')
for (var i = 0;i<e.length;i++){
     // older browser don't have element.classList -> even more complex
     e[i].children.classList.contains('foo');
     // do some more magic stuff here
}

3) aplique o estilo css

// .css('background-color', 'green')
// note different notation
element.style.backgroundColor = "green" // or
element.style["background-color"] = "green"

Esse código seria pelo menos duas vezes mais linhas de código que você escreve com o jQuery. Além disso, você deve considerar problemas entre navegadores que comprometam a grande vantagem de velocidade (além da confiabilidade) do código nativo.

Christoph
fonte
33
Que tipo de inconsistências querySelectorAllexistem entre navegadores? E como o jQuery resolveria isso, já que o jQuery usa querySelectorAll quando disponível?
3
É verdade que uma linha de código pode conter cadeias de códigos infinitos, o que pode ser muito irritante durante a depuração.
Dexter Huinda
1
"2) itere sobre a matriz de nós filhos através de alguns loops (possivelmente aninhados ou recursivos) e verifique a classe" << Esta é uma porcaria total. Você pode usar querySelectorAll no elemento na etapa anterior.
Vanuan
5
@Vanuan, isso pode não ser necessário, mas se você tivesse lido minuciosamente minha resposta, teria notado que o querySelector tem um sério problema de escopo que pode fornecer muitos falsos positivos quando usado da maneira que você propõe. No entanto, embora você esteja livre para votar em alto ou baixo por algum motivo, eu acho que não é um motivo para usar linguagem rude.
Christoph
2
@Christoph Como isso é fácil, eu adicionei compatibilidade para o IE8 e superior. Ainda enormes vantagens de velocidade (5-20 vezes). Que o código seja mais lento no navegador antigo como o IE8 é apenas uma suposição errada.
Pascalius
60

Se você estiver otimizando sua página para o IE8 ou mais recente, considere realmente se precisa de jquery ou não. Navegadores modernos têm muitos recursos nativamente fornecidos pelo jquery.

Se você gosta de desempenho, pode obter benefícios incríveis de desempenho (2-10 mais rápido) usando javascript nativo: http://jsperf.com/jquery-vs-native-selector-and-element-style/2

Transformei um div-tagcloud de jquery em javascript nativo (compatível com IE8 +), os resultados são impressionantes. 4 vezes mais rápido com um pouco de sobrecarga.

                    Number of lines       Execution Time                       
Jquery version :        340                    155ms
Native version :        370                    27ms

Você pode não precisar do Jquery fornece uma visão geral muito boa, quais métodos nativos substituem para qual versão do navegador.

http://youmightnotneedjquery.com/


Apêndice: Comparações mais rápidas de como os métodos nativos competem com o jquery

Pascalius
fonte
boa visão geral, apesar de alguns exemplos de código estarem errados ... Por exemplo, $(el).find(selector)não é igual el.querySelectorAll(selector)e o desempenho dos métodos nativos geralmente é bastante horrível: stackoverflow.com/q/14647470/1047823 #
Christoph
@Christoph Você pode elaborar, por que você acha que os métodos são diferentes? É claro que existem casos extremos nos quais o jquery pode ter um desempenho melhor, mas eu não vi um para manipulação de DOM.
Pascalius
1
Não há necessidade de elaborar mais, basta ler minha resposta, olhar para o violino e o artigo ao qual vinculei. Além disso, (pelo menos atm) a maioria dos métodos Array nativos é de velocidade inferior em comparação com uma implementação js ingênua (como eu vinculei na pergunta no meu primeiro comentário). E esses não são casos extremos, mas sim o caso padrão. Mas, novamente, o foco principal desta questão não era a velocidade.
Christoph
2
@Christoph É claro que esses métodos não são 100% iguais e o jquery geralmente oferece mais comodidade. Eu atualizei a resposta para mostrar que este é apenas um caso extremo, na verdade não consegui encontrar nenhum outro caso em que o jquery tivesse um desempenho melhor. Não há foco principal da questão.
Pascalius
+1 Excelente resposta! Eu tenho substituído lentamente o código antigo do jQuery por JavaScript bruto nos últimos 4 ou 5 anos, onde e sempre que possível. Claro, o jQuery é ótimo para algumas coisas e eu o uso para essas coisas quando sinto que tenho um benefício sólido.
Sim Barry
13

Para entender por que o jQuery é tão popular, é importante entender de onde viemos!

Cerca de uma década atrás, os principais navegadores eram IE6, Netscape 8 e Firefox 1.5. Naquela época, havia poucas maneiras entre navegadores para selecionar um elemento do DOM além Document.getElementById().

Então, quando o jQuery foi lançado em 2006 , foi bastante revolucionário. Naquela época, o jQuery definia o padrão de como selecionar / alterar facilmente elementos HTML e acionar eventos, porque sua flexibilidade e suporte ao navegador eram sem precedentes.

Agora, mais de uma década depois, muitos recursos que tornaram o jQuery tão popular foram incluídos no padrão javaScript:

Geralmente, eles não estavam disponíveis em 2005. O fato de estarem hoje obviamente implora a questão de por que deveríamos usar o jQuery. E, de fato, as pessoas estão cada vez mais se perguntando se devemos usar o jQuery .

Portanto, se você acha que entende JavaScript bem o suficiente para não usar o jQuery, por favor! Não se sinta obrigado a usar o jQuery, apenas porque muitos outros estão fazendo isso!

John Slegers
fonte
7

Isso porque o jQuery pode fazer muito mais do que querySelectorAll.

Primeiro, o jQuery (e o Sizzle, em particular), funciona para navegadores mais antigos, como o IE7-8, que não suporta seletores CSS2.1-3.

Além disso, o Sizzle (que é o mecanismo de seleção por trás do jQuery) oferece muitos instrumentos seletores mais avançados, como a :selectedpseudo-classe, um :not()seletor avançado , uma sintaxe mais complexa, como $("> .children")por exemplo.

E ele faz a navegação entre navegadores, na perfeição, oferecendo tudo o que o jQuery pode oferecer (plugins e APIs).

Sim, se você acha que pode confiar em seletores simples de classe e ID, o jQuery é demais para você e você pagaria um pagamento exagerado. Mas se não, e quiser tirar proveito de toda a bondade do jQuery, use-o.

MaxArt
fonte
7

O mecanismo seletor Sizzle do jQuery pode usar querySelectorAll se disponível. Ele também suaviza as inconsistências entre os navegadores para obter resultados uniformes. Se você não quiser usar todo o jQuery, poderá usar o Sizzle separadamente. Esta é uma roda bastante fundamental para inventar.

Aqui estão algumas escolhas da fonte que mostram o tipo de coisa que o jQuery (com Sizzle) classifica para você:

Modo peculiaridades do Safari:

if ( document.querySelectorAll ) {
  (function(){
    var oldSizzle = Sizzle,
      div = document.createElement("div"),
      id = "__sizzle__";

    div.innerHTML = "<p class='TEST'></p>";

    // Safari can't handle uppercase or unicode characters when
    // in quirks mode.
    if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
      return;
    }

Se esse guarda falhar, ele usa uma versão do Sizzle que não é aprimorada querySelectorAll. Mais abaixo, existem identificadores específicos para inconsistências no IE, Opera e no navegador Blackberry.

  // Check parentNode to catch when Blackberry 4.6 returns
  // nodes that are no longer in the document #6963
  if ( elem && elem.parentNode ) {
    // Handle the case where IE and Opera return items
    // by name instead of ID
    if ( elem.id === match[3] ) {
      return makeArray( [ elem ], extra );
    }

  } else {
    return makeArray( [], extra );
  }

E se tudo mais falhar, retornará o resultado de oldSizzle(query, context, extra, seed).

KGZM
fonte
6

Em termos de manutenção de código, há vários motivos para manter uma biblioteca amplamente usada.

Uma das principais é que elas estão bem documentadas e têm comunidades como ... digamos ... stackexchange, onde é possível encontrar ajuda com as bibliotecas. Com uma biblioteca codificada personalizada, você tem o código-fonte e talvez um documento de instruções, a menos que o (s) codificador (es) gastem mais tempo documentando o código do que escrevendo, o que é extremamente raro.

Escrever sua própria biblioteca pode funcionar para você , mas o estagiário sentado na mesa ao lado pode ter mais facilidade em se familiarizar com algo como jQuery.

Chame isso de efeito de rede, se quiser. Isso não quer dizer que o código seja superior no jQuery; apenas que a natureza concisa do código facilita a compreensão da estrutura geral para programadores de todos os níveis, mesmo que haja mais código funcional visível ao mesmo tempo no arquivo que você está visualizando. Nesse sentido, 5 linhas de código são melhores que 10.

Para resumir, vejo os principais benefícios do jQuery como sendo código conciso e onipresença.

Dom Day
fonte
6

Aqui está uma comparação se eu quiser aplicar o mesmo atributo, por exemplo, ocultar todos os elementos da classe "minha classe". Esse é um dos motivos para usar o jQuery.

jQuery:

$('.my-class').hide();

JavaScript:

var cls = document.querySelectorAll('.my-class');
for (var i = 0; i < cls.length; i++) {
    cls[i].style.display = 'none';
}

Com o jQuery já tão popular, eles deveriam ter feito document.querySelector () se comportar como $ (). Em vez disso, document.querySelector () seleciona apenas o primeiro elemento correspondente, o que o torna apenas parcialmente útil.

Steven
fonte
4
Eu faria um .para cada um aqui.
Phillip Senn #
Bem, você sempre pode seguir uma rota mais fácil document.querySelectorAll('.my-class').forEach(el => el.style.display = 'none');. Mesmo que seja mais curto, o desempenho nativo é sempre melhor.
Alain Cruz
Do ponto de vista do usuário, tudo o que acontece em menos de 0,1 s acontece imediatamente. Portanto, o nativo é ainda mais rápido, melhor apenas no caso de a implementação do jQuery ser mais lenta que 0,1 seg. E na aplicação do mundo real, nunca é o caso.
yurin 8/01
3

como diz o site oficial: "jQuery: escreva menos, faça mais, biblioteca JavaScript"

tente traduzir o seguinte código jQuery sem nenhuma biblioteca

$("p.neat").addClass("ohmy").show("slow");
simon xu
fonte
1
Concordo com isso, no entanto, e a legibilidade? como você pode documentar longas linhas de código com muitas coisas não relacionadas acontecendo? Como você pode depurar essas monstruosidades?
Joel_Blum 16/07
@ user1032663 é uma questão de documentação-convenções.
Christoph
1
A alternativa ao jQuery (ou qualquer outra biblioteca "popular" que você escolher) não é escrever tudo do zero, mas usar uma biblioteca que atenda ao seu objetivo e esteja bem escrita. Você mesmo pode ter escrito partes ou escolhido uma biblioteca modular como MyLibrary para incluir apenas o que precisa.
22912 RobG #
2
O exemplo que você escolheu não prova realmente o seu ponto: a questão está em busca de diferenças na província "seletora". addClass()e show()realmente não contam. E quanto a $('p.neat'), você pode dar uma olhada no querySelector / All.
kumarharsh
document.querySelectorAll('p.neat').forEach(p=>p.classList.add('ohmy'));e deixe o CSS fazer o resto. Código ligeiramente mais longo, mas muito mais eficiente. Obviamente, sua solução não estava tão disponível nos dias do Legacy IE. A parte "Faça mais" é irônica. O jQuery leva cerca de cem linhas de código para encontrar algo; portanto, fazer mais nem sempre é produtivo.
Manngo 12/03
2

Eu acho que a verdadeira resposta é que o jQuery foi desenvolvido muito antes querySelector/querySelectorAll se tornar disponível em todos os principais navegadores.

O lançamento inicial do jQuery foi em 2006 . De fato, nem o jQuery foi o primeiro a implementar seletores de CSS .

O IE foi o último navegador a implementar querySelector/querySelectorAll. Sua 8ª versão foi lançada em 2009 .

Portanto, agora, os seletores de elementos DOM não são mais o ponto mais forte do jQuery. No entanto, ele ainda tem muitas novidades na manga, como atalhos para alterar o conteúdo css e html do elemento, animações, associação de eventos e ajax.

Vanuan
fonte
1

Pergunta antiga, mas meia década depois, vale a pena revisar. Aqui estou discutindo apenas o aspecto seletor do jQuery.

document.querySelector[All]é suportado por todos os navegadores atuais, até o IE8, portanto, a compatibilidade não é mais um problema. Também não encontrei problemas de desempenho para falar (era para ser mais lento do que document.getElementById, mas meus próprios testes sugerem que é um pouco mais rápido).

Portanto, quando se trata de manipular um elemento diretamente, é preferível ao jQuery.

Por exemplo:

var element=document.querySelector('h1');
element.innerHTML='Hello';

é muito superior a:

var $element=$('h1');
$element.html('hello');

Para fazer qualquer coisa, o jQuery precisa percorrer uma centena de linhas de código (uma vez rastreiei um código como o acima para ver o que o jQuery estava realmente fazendo com ele). Isso é claramente uma perda de tempo de todos.

O outro custo significativo do jQuery é o fato de envolver tudo dentro de um novo objeto jQuery. Essa sobrecarga é particularmente inútil se você precisar desembrulhar o objeto novamente ou usar um dos métodos do objeto para lidar com propriedades que já estão expostas no elemento original.

Onde o jQuery tem uma vantagem, no entanto, é como ele lida com coleções. Se o requisito é definir propriedades de vários elementos, o jQuery possui um eachmétodo interno que permite algo como isto:

var $elements=$('h2');  //  multiple elements
$elements.html('hello');

Para fazer isso com o Vanilla JavaScript seria necessário algo como isto:

var elements=document.querySelectorAll('h2');
elements.forEach(function(e) {
    e.innerHTML='Hello';
});

que alguns acham assustador.

Os seletores de jQuery também são um pouco diferentes, mas os navegadores modernos (excluindo o IE8) não terão muitos benefícios.

Como regra, eu aviso contra o uso do jQuery para novos projetos:

  • O jQuery é uma biblioteca externa que contribui para a sobrecarga do projeto e para a sua dependência de terceiros.
  • A função jQuery é muito cara, em termos de processamento.
  • O jQuery impõe uma metodologia que precisa ser aprendida e pode competir com outros aspectos do seu código.
  • O jQuery demora a expor novos recursos em JavaScript.

Se nenhuma das opções acima importa, faça o que quiser. No entanto, o jQuery não é mais tão importante para o desenvolvimento em várias plataformas como costumava ser, pois o JavaScript e o CSS modernos vão muito além do que costumavam ser.

Isso não menciona outros recursos do jQuery. No entanto, acho que eles também precisam de um olhar mais atento.

Manngo
fonte
1
Sua sintaxe não é correta nem para mencionar outras coisas erradas, como "lento para expor novos recursos em Javascript". O trabalho do JQuery não é nem mesmo para expor novos recursos, é para facilitar a manipulação do DOM e fazer coisas simples que poderiam ser como 10 linhas em Javascript. Todo o seu comentário simplesmente não faz sentido e tem muitas coisas erradas. Considere melhorá-lo.
Boy pro
@ Boypro Obrigado pelo seu comentário, mas ele também está cheio de erros. Talvez você queira compartilhar o que há com a minha resposta que o ofende tanto. O que é "nem mesmo correto". Melhor ainda, você pode contribuir com sua própria resposta. A questão é sobre o custo do uso do jQuery quando o JavaScript vanilla pode fazer muito. Considere responder.
Manngo 30/08/19
0
$ ("# id") vs document.querySelectorAll ("# id")

O negócio é com a função $ () que cria uma matriz e depois a divide para você, mas com document.querySelectorAll () ele cria uma matriz e você precisa dividi-la.


fonte
0

Apenas um comentário sobre isso, ao usar o material design lite, o seletor jquery não retorna a propriedade para o design do material por algum motivo.

Para:

<div class="logonfield mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
        <input class="mdl-textfield__input" type="text" id="myinputfield" required>
        <label class="mdl-textfield__label" for="myinputfield">Enter something..</label>
      </div>

Isso funciona:

document.querySelector('#myinputfield').parentNode.MaterialTextfield.change();

Isto não:

$('#myinputfield').parentNode.MaterialTextfield.change();
Ashvin Bhuttoo
fonte