Un collègue avec qui je travaille dit que la bonne façon de vérifier devrait être :
if ($( "#myDiv" ) && $( "#myDiv" ).length ) {
//do something
}
Il a tort, du moins en ce qui concerne la partie $( "#myDiv" ) &&
. La méthode $(selector)
de jQuery retourne toujours un objet, qui est toujours truthy par définition. Donc cette partie est inutile et re-requêter le DOM pour rien.
Je veux dire au niveau des performances ou de la latence, est-ce qu'ils sont égaux ?
Re-querer le DOM pour rien est une perte de temps, mais la plupart du temps cela n'a pas d'impact observable, et surtout pas pour les sélecteurs ID comme $("#myDiv")
qui sont optimisés par jQuery en appels à getElementById
(qui est ultra-rapide). Donc d'une part, oui c'est du travail supplémentaire inutile. D'autre part, les navigateurs sont tellement rapides de nos jours que vous avez probablement d'autres préoccupations. Mais c'est probablement du code supplémentaire inutile, ce qui est le plus gros problème.
Concernant le point général : jQuery est basé sur des ensembles. Cela signifie que les opérations sur des ensembles sans éléments ne font rien. Par exemple :
$(".foo").addClass("bar");
...est une non-opération (pas une erreur) si aucun élément .foo
n'est dans le DOM.
Donc vérifiez la length
quand vous voulez savoir si vous avez trouvé des éléments. Si cela ne vous importe pas et que vous voulez simplement effectuer des opérations sur eux s'ils sont là, faites simplement l'opération (avec une importante mise en garde1).
Donc en gros, il y a trois scénarios :
-
Vous savez que les éléments seront là, donc la vérification est inutile
\=> pas de vérification
-
Vous ne savez pas si les éléments seront là, mais cela vous importe peu et vous voulez simplement opérer sur eux si ils sont là
\=> pas de vérification
-
Vous voulez savoir si les éléments sont là pour une autre raison
\=> faites la vérification
1 Voici la mise en garde importante : si vous appelez une fonction jQuery qui retourne quelque chose d'autre qu'un objet jQuery (par exemple, val()
ou offset()
ou position()
, etc.), quand vous l'appelez sur un ensemble vide, cela retournera typiquement undefined
(l'exception est text()
, qui retournera ""
[text()
n'est pas comme les autres à plusieurs égards; c'en est un]). Donc écrire du code qui suppose naïvement que ces choses retourneront ce que vous attendez, même quand l'ensemble est vide, vous causera des problèmes.
Par exemple :
if ($(".foo").offset().top > 20)
...va générer une erreur s'il n'y a pas d'éléments .foo
, car offset()
retournera undefined
, pas un objet.
Mais cela est bon :
$(".foo").closest(".bar").toggleClass("baz"):
...car même s'il n'y a pas de .foo
, closest()
retournera un autre ensemble jQuery vide, et appeler toggleClass()
dessus ne fera rien.
Donc quand vous manipulez un accesseur qui ne retourne pas un objet jQuery, si vous ne savez pas avec certitude que vous manipulez un ensemble contenant au moins un élément, vous avez besoin de plus de défense, par exemple :
var offset = $(".foo").offset();
if (offset && offset.top > 20)
Encore une fois, la plupart des accesseurs (qui ne retournent pas d'objets jQuery) fonctionnent ainsi, y compris val()
, offset()
, position()
, css()
, ...