desempenho seletor jQuery
-
05-07-2019 - |
Pergunta
Eu estou tendo grandes variações de desempenho, dependendo de como eu expressar meus seletores. Por exemplo, olhar para estes 2 seletores, que selecionar exatamente os mesmos elementos:
A) someTableRow.find("td.someColumnClass").find("span.editMode").find("input")
B) someTableRow.find("td.someColumnClass span.editMode input")
Eu esperaria B) para ser mais rápido, há apenas 1 chamada, mas na verdade eu estou achando A) executa cerca de 8 vezes mais rápido. Eu não tenho idéia por que, alguém tem alguma idéia? Graças
Solução
Supondo que você está usando pelo menos jQuery 1.3 (ou seja, com a adição de Sizzle), o desempenho que você está vendo é devido à mudança em que o DOM é atravessado. De aqui :
Até e incluindo jQuery 1.2.6 do motor selector trabalhou em um "down top" (Ou "esquerda para a direita") forma. jQuery 1.3.x (ou seja, chiar , que incorpora jQuery) introduziu um "-se inferior" (ou "Direita para a esquerda") abordagem para consulta DOM.
Em seu segundo exemplo ("td.someColumnClass span.editMode input"
), Sizzle efetivamente faz isso:
- obter todos os elementos
input
dentrosomeTableRow
- para cada elemento
input
encontrado, atravessar a sua árvore ancestral para elementosspan
comclass="editMode"
. Remover elementosinput
que não têm esses ancestrais - para cada elemento
span.editMode
encontrado, atravessar a sua árvore ancestral para elementostd
comclass="someColumnClass"
. Remover elementosinput
que não têm esses ancestrais
Em seu primeiro exemplo no entanto, você está qualificando cada etapa explicitamente com cada chamada para find()
, definindo um contexto e atravessando abaixo de lá. Você está aplicando a abordagem "top-down". É equivalente ao passar num contexto em cada etapa, o que é geralmente considerado um desempenho reforço:
$('input', $('span.editMode', $('td.someColumnClass', someTableRow)))
Outras dicas
Porque você está reduzindo o contexto para a pesquisa.
No caso B, tem que pesquisar através de cada elemento DOM para ver se ele atende aos critérios.
No caso de A, é rapidamente pode decidir ignorar qualquer coisa que não é "td.someColumnClass", então ele pode tomar esse subconjunto do DOM e ignorar qualquer coisa que não está em "span.editMode". Por isso, tem um conjunto muito menor de elementos a pesquisar para encontrar "input" é agora.
A é mais chamadas, mas mais simples. B é uma chamada, mas mais complexa. Neste caso, a complexidade da chamada muito out-pesa a quantidade de chamadas.
A forma como as alças JQuery selctors é um pouco diferente para CSS na minha experiência.
Reduzir o contexto para a pesquisa é a chave como Josh apontou.
I encontrar usando os dois seletores de parâmetros muito rápido
Como é que esta velocidade comparar sábio?
Você não precisa de todos os vars aqui é apenas para deixar claro o que estou fazendo.
var columnClasses = $('.someColumnClass');
var tableCell = $('td', columnclasses);
var editMode = $('.editmode', tableCell);
var spanInside = $('span', editMode);
var inputFinally = $('input', spanInside);
Bondade,
Dan
Eu fiz alguma pesquisa sobre jQuery Selector Desempenho mim. Um grande problema são as pesquisas por nome de classe no Internet Explorer. IE suporte does not getElementsByClassName - portanto, jQuery e outras estruturas "Reimplementar"-lo em JavaScript por iteração através de todos os elementos DOM. Confira a seguir blogue análise sobre jQuery Selector Desempenho
Há um artigo muito interessante sobre o desempenho selector aqui: http: // blogs .atlassian.com / desenvolvedor / 2009/08 / jquery_bondage.html
Nele, o autor mostra um "bind" extensão jQuery que mostra quantas vezes a função é avaliada.