Quand utiliser Vanilla JavaScript vs jQuery?

238

J'ai remarqué en surveillant / essayant de répondre aux questions courantes de jQuery, qu'il existe certaines pratiques utilisant javascript, au lieu de jQuery, qui vous permettent en fait d' écrire moins et de faire ... bien le même montant. Et peut également apporter des avantages en termes de performances.

Un exemple concret

$(this) contre this

À l'intérieur d'un événement click référençant l'id des objets cliqués

jQuery

$(this).attr("id");

Javascript

this.id;

Y a-t-il d'autres pratiques courantes comme celle-ci? Où certaines opérations Javascript pourraient être accomplies plus facilement, sans amener jQuery dans le mix. Ou est-ce un cas rare? (d'un "raccourci" jQuery nécessitant en fait plus de code)

EDIT: Bien que j'apprécie les réponses concernant les performances de jQuery vs javascript simple, je suis en fait à la recherche de réponses beaucoup plus quantitatives. Lors de l'utilisation de jQuery , les cas où il serait préférable (lisibilité / compacité) d'utiliser du javascript simple au lieu d'utiliser $(). En plus de l'exemple que j'ai donné dans ma question initiale.

jondavidjohn
la source
Je ne suis pas sûr de comprendre la question. Cherchiez-vous des opinions sur le bien-fondé de l'utilisation du code de bibliothèque, ou recherchiez-vous des techniques supplémentaires non compatibles avec jQuery et compatibles avec plusieurs navigateurs this.id?
user113716
1
à partir des réponses, il semble que tout le monde considère cette question comme philosophique, car je voulais qu'elle soit très quantitative, comme pour presque compiler une liste d'instances comme celle que j'ai décrite qui sont des pratiques (mal) courantes.
jondavidjohn

Réponses:

207
  • this.id (comme vous le savez)
  • this.value(sur la plupart des types d'entrée. seuls les problèmes que je connais sont IE quand un <select>n'a pas de valuepropriétés définies sur ses <option>éléments, ou des entrées radio dans Safari.)
  • this.className pour obtenir ou définir une propriété "classe" entière
  • this.selectedIndexcontre un <select>pour obtenir l'index sélectionné
  • this.optionscontre un <select>pour obtenir une liste d' <option>éléments
  • this.textcontre un <option>pour obtenir son contenu textuel
  • this.rowscontre un <table>pour obtenir une collection d' <tr>éléments
  • this.cellscontre a <tr>pour obtenir ses cellules (td & th)
  • this.parentNode avoir un parent direct
  • this.checkedpour obtenir l'état vérifié d'un checkbox Thanks @Tim Down
  • this.selectedpour obtenir l'état sélectionné d'un option Thanks @Tim Down
  • this.disabledobtenir l'état désactivé d'un input Thanks @Tim Down
  • this.readOnlypour obtenir l'état readOnly d'un input Thanks @Tim Down
  • this.hrefcontre un <a>élément pour obtenir sonhref
  • this.hostnamecontre un <a>élément pour obtenir le domaine de sonhref
  • this.pathnamecontre un <a>élément pour obtenir le chemin de sonhref
  • this.searchcontre un <a>élément pour obtenir la chaîne de requête de sonhref
  • this.src contre un élément où il est valable d'avoir un src

... Je pense que vous avez l'idée.

Il y aura des moments où la performance sera cruciale. Comme si vous exécutez plusieurs fois une boucle, vous pouvez abandonner jQuery.

En général, vous pouvez remplacer:

$(el).attr('someName');

avec:

Ci-dessus était mal formulé. getAttributen'est pas un remplacement, mais il récupère la valeur d'un attribut envoyé par le serveur, et son correspondant setAttributele définira. Nécessaire dans certains cas.

Les phrases ci-dessous l'ont en quelque sorte couvert. Voir cette réponse pour un meilleur traitement.

el.getAttribute('someName');

... afin d'accéder directement à un attribut. Notez que les attributs ne sont pas les mêmes que les propriétés (bien qu'ils se reflètent parfois). Bien sûr, il y en a setAttributeaussi.

Disons que vous avez eu une situation où vous avez reçu une page où vous devez déballer toutes les balises d'un certain type. C'est court et facile avec jQuery:

$('span').unwrap();  // unwrap all span elements

Mais s'il y en a beaucoup, vous voudrez peut-être faire une petite API DOM native:

var spans = document.getElementsByTagName('span');

while( spans[0] ) {
    var parent = spans[0].parentNode;
    while( spans[0].firstChild ) {
        parent.insertBefore( spans[0].firstChild, spans[0]);
    }
    parent.removeChild( spans[0] );
}

Ce code est assez court, il fonctionne mieux que la version jQuery et peut facilement être transformé en fonction réutilisable dans votre bibliothèque personnelle.

Il peut sembler que j'ai une boucle infinie avec l'extérieur à whilecause de while(spans[0]), mais parce que nous avons affaire à une "liste en direct", elle est mise à jour lorsque nous faisons le parent.removeChild(span[0]);. C'est une fonctionnalité assez astucieuse que nous manquons lorsque nous travaillons avec un tableau (ou un objet semblable à un tableau) à la place.

user113716
la source
2
sympa ... donc la plupart du temps, il tourne autour du fait que ce mot-clé est enroulé sans nécessité dans un objet jQuery.
jondavidjohn
1
@jondavidjohn: Eh bien, il y a des correctifs qui sont bien dans certains cas, comme this.valueoù il y a quelques bizarreries de navigateur dans certains cas. Tout dépend de vos besoins. Il existe de nombreuses techniques agréables qui sont faciles sans jQuery, en particulier lorsque les performances sont cruciales. Je vais essayer de penser à plus.
user113716
3
J'étais sur le point d'écrire une réponse, mais à la place, j'ajouterai des suggestions pour la vôtre. En général, attr()est massivement surutilisé. Si vous n'avez affaire qu'à un seul élément, vous en aurez rarement besoin attr(). Deux de mes favoris sont la confusion autour de la checkedpropriété de cases à cocher (toutes sortes d'incantations mystiques autour de celle - là: $(this).attr("checked", "checked"), $(this).is(":checked")etc.) et de même la selectedpropriété des <option>éléments.
Tim Down
1
Aaargh, @patrick, noooo: vous avez recommandé getAttribute(). Vous n'en avez presque jamais besoin : il est cassé dans IE, ne reflète pas toujours l'état actuel et ce n'est pas ce que jQuery fait de toute façon. Utilisez simplement les propriétés. stackoverflow.com/questions/4456231/…
Tim Down
1
J'utilisais JS depuis si longtemps et je ne connaissais pas className, thx.
IAdapter
60

La bonne réponse est que vous subirez toujours une baisse de performances lors de l'utilisation de jQuery au lieu du JavaScript natif «simple». C'est parce que jQuery est une bibliothèque JavaScript. Ce n'est pas une nouvelle version sophistiquée de JavaScript.

La raison pour laquelle jQuery est puissant est qu'il rend certaines choses trop fastidieuses dans une situation multi-navigateur (AJAX est l'un des meilleurs exemples) et atténue les incohérences entre la myriade de navigateurs disponibles et fournit une API cohérente. Il facilite également facilement des concepts tels que le chaînage, l'itération implicite, etc., pour simplifier le travail sur des groupes d'éléments ensemble.

L'apprentissage de jQuery ne remplace pas l'apprentissage de JavaScript. Vous devez avoir une base solide dans ce dernier afin que vous puissiez pleinement apprécier ce que la connaissance du premier vous facilite.

- Modifié pour englober les commentaires -

Comme les commentaires sont rapides à souligner (et je suis d'accord avec 100%), les déclarations ci-dessus se réfèrent au code de référence. Une solution JavaScript «native» (en supposant qu'elle soit bien écrite) surclassera une solution jQuery qui accomplit la même chose dans presque tous les cas (j'adorerais voir un exemple autrement). jQuery accélère le temps de développement, ce qui est un avantage important que je ne veux pas minimiser. Il facilite un code facile à lire et à suivre, ce qui est plus que certains développeurs sont capables de créer par eux-mêmes.

À mon avis, la réponse dépend donc de ce que vous essayez de réaliser. Si, comme je l'ai présumé sur la base de votre référence aux avantages de performances, vous recherchez la meilleure vitesse possible de votre application, alors l'utilisation de jQuery introduit des frais généraux à chaque appel $(). Si vous optez pour la lisibilité, la cohérence, la compatibilité entre navigateurs, etc., il y a certainement des raisons de privilégier jQuery sur JavaScript «natif».

gddc
la source
8
J'aimerais voir un exemple d'une situation où jQuery peut surpasser une implémentation en JS pur. Peu importe ce que vous faites, si vous utilisez jQuery (ou toute autre bibliothèque d'ailleurs), vous avez une surcharge de fonction qui est inévitable. Il n'y a aucun moyen de s'éloigner de la surcharge (quoique) mineure générée par l'appel $(). Si vous ne faites pas cet appel, vous gagnez du temps.
gddc
16
Une solution maison mal écrite serait probablement plus lente. L'équipe jQuery a exécuté du JavaScript très efficace dans le package. Voir la réponse de @ Freelancer.
Stephen
3
Une solution mal écrite sera toujours une solution mal écrite, et ce n'est pas la faute de la langue. Cela ne change pas le fait que la bibliothèque entraînera des frais généraux qu'une fonction «native» pourrait éviter si elle était bien pensée.
gddc
11
@gddc Je pense que le meilleur exemple où jQuery "surpasse" (lu en dehors de la boîte de référence) est de réduire le temps de développement (c'est une valeur énorme sur le plan commercial) et de simplifier l'expérimentation
Ben
13
Tout ce que vous avez écrit est vrai, mais vous avez omis ce que @Ben note ci-dessus. jQuery rend le développeur plus rapide et plus robuste. Voir cette implémentation de KillClass () que j'ai écrite il y a plusieurs années et que j'ai beaucoup utilisée. Vous savez quoi? Il est cassé pour certains cas de bord. Un mauvais code est un mauvais code et un mauvais code est un mauvais code, mais l'utilisation de jQuery permet souvent au développeur d'écrire un code meilleur et plus correct. La plupart du temps, les ordinateurs sont assez rapides; ce sont les développeurs qui ont besoin d'aide.
Phrogz
38

Il y a un cadre appelé ... oh devinez quoi? Vanilla JS. J'espère que vous obtenez la blague ...: D Il sacrifie la lisibilité du code pour les performances ... En le comparant à jQueryci-dessous, vous pouvez voir que la récupération d'un DOMélément par IDest presque 35X plus rapide. :)

Donc, si vous voulez des performances, vous feriez mieux d'essayer Vanilla JS et de tirer vos propres conclusions. Peut-être que vous ne rencontrerez pas JavaScript pour bloquer l'interface graphique du navigateur / verrouiller le thread d'interface utilisateur pendant le code intensif comme dans une forboucle.

Vanilla JS est un framework multiplateforme rapide et léger pour créer des applications JavaScript incroyables et puissantes.

Sur leur page d'accueil, il y a des comparaisons de performances:

entrez la description de l'image ici

Leniel Macaferi
la source
1
@Leniel Macaferi Oh Man, j'ai adoré cette réponse! Je n'avais pas réalisé que les performances entre vanilla et d'autres frameworks pouvaient faire une telle différence! Quoi qu'il en soit Hall of fame pour cette réponse !! PS: Avez-vous également créé le site Web?
Steve
17

Il existe déjà une réponse acceptée, mais je pense qu'aucune réponse tapée directement ici ne peut être complète dans sa liste de méthodes / attributs javascript natifs qui a pratiquement garanti la prise en charge de plusieurs navigateurs. Pour cela, je peux vous rediriger vers quirksmode:

http://www.quirksmode.org/compatibility.html

C'est peut-être la liste la plus complète de ce qui fonctionne et de ce qui ne fonctionne pas sur quel navigateur. Portez une attention particulière à la section DOM. C'est beaucoup à lire mais il ne s'agit pas de tout lire mais de l'utiliser comme référence.

Lorsque j'ai commencé à écrire sérieusement des applications Web, j'ai imprimé toutes les tables DOM et les ai accrochées au mur pour que je sache en un coup d'œil ce qui est sûr à utiliser et ce qui nécessite des hacks. Ces jours-ci, je google juste quelque chose commequirksmode parentNode compatibility quand j'ai des doutes.

Comme toute autre chose, le jugement est surtout une question d'expérience. Je ne vous recommanderais pas vraiment de lire l'intégralité du site et de mémoriser tous les problèmes pour savoir quand utiliser jQuery et quand utiliser JS ordinaire. Soyez juste au courant de la liste. C'est assez facile à rechercher. Avec le temps, vous développerez un instinct quand le JS simple est préférable.


PS: PPK (l'auteur du site) a également un très beau livre que je recommande de lire

Slebetman
la source
14

Quand:

  1. vous savez que ce que vous faites est compatible avec tous les navigateurs, et
  2. ce n'est pas beaucoup plus de code à taper, et
  3. il n'est pas beaucoup moins lisible, et
  4. vous êtes raisonnablement convaincu que jQuery ne choisira pas différentes implémentations basées sur le navigateur pour obtenir de meilleures performances, alors:

utilisez JavaScript. Sinon, utilisez jQuery (si vous le pouvez).

Modifier : Cette réponse s'applique à la fois lorsque vous choisissez d'utiliser jQuery dans son ensemble plutôt que de le laisser de côté, ainsi que de choisir d'utiliser ou non la vanille JS dans jQuery. Choisir entre attr('id')et .idpenche en faveur de JS, tout en choisissant entre removeClass('foo')versus .className = .className.replace( new Regexp("(?:^|\\s+)"+foo+"(?:\\s+|$)",'g'), '' )penche en faveur de jQuery.

Phrogz
la source
3
Je pense que l'OP a l'intention d'utiliser jQuery, mais se demande où et quand utiliser JavaScript natif dans ses méthodes jQuery.
Stephen
.classList.remove('foo')semble bien fonctionner dans les nouveaux navigateurs
Tyilo
3
@Tyilo classList.remove fait partie de l'API HTML5 ClassList qui n'est pas implémentée dans IE9 par exemple caniuse.com/#feat=classlist
corbacho
13

Les réponses des autres se sont concentrées sur la vaste question «jQuery vs plain JS». À en juger par votre OP, je pense que vous vous demandiez simplement quand il est préférable d'utiliser vanilla JS si vous avez déjà choisi d'utiliser jQuery. Votre exemple est un exemple parfait de quand vous devez utiliser vanilla JS:

$(this).attr('id');

Est à la fois plus lent et (à mon avis) moins lisible que:

this.id.

C'est plus lent car vous devez faire tourner un nouvel objet JS juste pour récupérer l'attribut de la manière jQuery. Maintenant, si vous allez utiliser $(this)pour effectuer d'autres opérations, stockez cet objet jQuery dans une variable et opérez avec cela. Cependant, j'ai rencontré de nombreuses situations où j'ai juste besoin d'un attribut de l'élément (comme idou src).

Y a-t-il d'autres pratiques courantes comme celle-ci? Où certaines opérations Javascript pourraient être accomplies plus facilement, sans amener jQuery dans le mix. Ou est-ce un cas rare? (d'un "raccourci" jQuery nécessitant en fait plus de code)

Je pense que le cas le plus courant est celui que vous décrivez dans votre message; les gens enveloppant $(this)inutilement un objet jQuery. Je vois cela le plus souvent avec idet value(à la place $(this).val()).

Edit: Voici un article qui explique pourquoi utiliser jQuery dans le attr()cas est plus lent. Confession: volé le tag wiki, mais je pense que cela vaut la peine d'être mentionné pour la question.

Modifier à nouveau: Étant donné les implications en termes de lisibilité / performances d'un accès direct aux attributs, je dirais qu'une bonne règle de base est probablement d'essayer d'utiliser this.<attributename>lorsque cela est possible. Il y a probablement des cas où cela ne fonctionnera pas en raison des incohérences du navigateur, mais il est probablement préférable d'essayer d'abord et de revenir sur jQuery si cela ne fonctionne pas.

Andrew Whitaker
la source
hah, merci d'avoir lu la question;) ... c'est donc plus largement l'exception?
jondavidjohn
@jondavidjohn: Honnêtement, j'hésite à faire cet appel. Je pense que oui, il est généralement à votre avantage d'utiliser jQuery en raison de problèmes croisés entre les navigateurs. Il y a d'autres exemples, comme this.style.display = 'none'. Est-ce mieux que ça $(this).hide()? Je dirais que ce dernier est plus lisible, mais le premier est probablement plus rapide. Cela ne fait pas de mal de faire des expériences vous-même pour voir si certaines actions fonctionneront sur tous les navigateurs sans jQuery - C'est généralement ce que je fais avant d'envelopper un élément dans un objet jQuery pour effectuer une opération.
Andrew Whitaker
10

Si vous êtes principalement préoccupé par la performance, votre exemple principal frappe le clou sur la tête. Invoquer jQuery inutilement ou de manière redondante est, à mon humble avis, la deuxième cause principale de ralentissement des performances (la première étant une mauvaise traversée du DOM).

Ce n'est pas vraiment un exemple de ce que vous recherchez, mais je le vois si souvent qu'il vaut la peine de le mentionner: l'une des meilleures façons d'accélérer les performances de vos scripts jQuery est de mettre en cache les objets jQuery et / ou d'utiliser le chaînage:

// poor
$(this).animate({'opacity':'0'}, function() { $(this).remove(); });

// excellent
var element = $(this);
element.animate({'opacity':'0'}, function() { element.remove(); });

// poor
$('.something').load('url');
$('.something').show();

// excellent
var something = $('#container').children('p.something');
something.load('url').show();
Stephen
la source
intéressant ... cette séparation de l'instanciation et de l'action var conduit-elle réellement à des gains de performances de traitement? ou permet simplement à l'action de s'exécuter seule (ce qui la rend moins encombrée, je suppose ...)
jondavidjohn
1
Cela conduit très certainement à des gains de performances, mais uniquement si vous réutilisez l'élément sélectionné. Donc, dans le dernier cas var something, je n'avais pas vraiment besoin de mettre en cache l'objet jQuery (puisque j'ai utilisé le chaînage), mais je le fais quand même par habitude.
Stephen
2
D'un autre côté, prenez le même exemple. Appeler $('.something')deux fois signifie que jQuery doit traverser le DOM deux fois en recherchant tous les éléments avec ce sélecteur.
Stephen
2
Dans le cas du premier exemple, la mise en cache $(this)réduit les appels à la fonction jQuery. Cela vous donnera le plus de gain dans un scénario en boucle.
Stephen
2
@Alnitak Notez que elementc'est égal à $(this). Cela ne contient pas plusieurs éléments.
Stephen
8

J'ai trouvé qu'il y a certainement un chevauchement entre JS et JQ. Le code que vous avez montré en est un bon exemple. Franchement, la meilleure raison d'utiliser JQ sur JS est simplement la compatibilité du navigateur. Je penche toujours vers JQ, même si je peux accomplir quelque chose dans JS.

Dutchie432
la source
8
Ce serait une merveille s'il n'y avait pas de chevauchement, car JQuery est JavaScript.
Simon
6

C'est mon point de vue personnel, mais comme jQuery est de toute façon JavaScript, je pense qu'il ne peut théoriquement pas mieux fonctionner que vanilla JS.

Mais en pratique, il peut fonctionner mieux que JS écrit à la main, car son code manuscrit peut ne pas être aussi efficace que jQuery.

En bout de ligne - pour les petites choses, j'ai tendance à utiliser la vanille JS, pour les projets intensifs JS j'aime utiliser jQuery et ne pas réinventer la roue - c'est aussi plus productif.

CodeVirtuoso
la source
1
Il existe de nombreux exemples où les bibliothèques surpassent vanilla JS. Beaucoup de méthodes prototypes intégrées de JS sont mal écrites, il s'avère.
Statistiques d'apprentissage par l'exemple du
3

La liste des propriétés en direct de la première réponse en thistant qu'élément DOM est assez complète.

Vous pouvez également trouver intéressant d'en connaître d'autres.

Quand c'est le document:

  • this.formspour obtenir l'un HTMLCollectiondes formulaires de document actuels,
  • this.anchorspour obtenir un HTMLCollectionde tous HTMLAnchorElementsavec nameêtre réglé,
  • this.linkspour obtenir un HTMLCollectionde tous les HTMLAnchorElements avec le hrefréglage,
  • this.imagespour obtenir un HTMLCollectionde tous les HTMLImageElements
  • et la même chose avec les applets obsolètes comme this.applets

Lorsque vous travaillez avec document.forms, document.forms[formNameOrId]obtient le formulaire ainsi nommé ou identifié.

Lorsqu'il s'agit d'un formulaire:

  • this[inputNameOrId] pour obtenir le champ ainsi nommé ou identifié

Lorsqu'il s'agit d'un champ de formulaire:

  • this.type pour obtenir le type de champ

Lors de l'apprentissage des sélecteurs jQuery, nous ignorons souvent l'apprentissage des propriétés des éléments HTML déjà existants, qui sont si rapides d'accès.

lib3d
la source
Les propriétés que vous avez mentionnées sont définies dans la spécification HTML DOM niveau 2 et largement prises en charge. document.embedset document.pluginssont également largement pris en charge (DOM 0). document.scriptsest également une collection pratique, définie dans la spécification HTML5 et largement prise en charge (et Firefox 9+ ).
Rob W
@Robw La liste pourrait donc maintenant être complète, et certainement utile et rapide. Merci;)
lib3d
2

Comme d'habitude, je viens en retard à cette fête.

Ce n'est pas la fonctionnalité supplémentaire qui m'a fait décider d'utiliser jQuery, aussi attrayant que cela ait été. Après tout, rien ne vous empêche d'écrire vos propres fonctions.

C'était le fait qu'il y avait tellement de trucs à apprendre lors de la modification du DOM pour éviter les fuites de mémoire (je parle de vous IE). Avoir une ressource centrale qui a géré tous ces types de problèmes pour moi, écrit par des gens qui étaient beaucoup mieux que les codeurs JS que je ne serai jamais, qui était continuellement examiné, révisé et testé était envoyé par Dieu.

Je suppose que ce genre de problème relève de l'argument du support / abstraction de plusieurs navigateurs.

Et bien sûr, jQuery n'interdit pas l'utilisation de JS droit lorsque vous en avez besoin. J'ai toujours senti que les deux semblaient fonctionner ensemble de façon transparente.

Bien sûr, si votre navigateur n'est pas pris en charge par jQuery ou si vous prenez en charge un environnement bas de gamme (ancien téléphone?), Un gros fichier .js peut être un problème. Rappelez-vous quand jQuery était petit?

Mais normalement, la différence de performances n'est pas un sujet de préoccupation. Cela ne doit être que suffisamment rapide. Avec des Gigahertz de cycles CPU à perdre chaque seconde, je suis plus préoccupé par les performances de mes codeurs, les seules ressources de développement qui ne doublent pas tous les 18 mois.

Cela dit, je suis actuellement à la recherche de problèmes d'accessibilité et, apparemment, .innerHTML est un peu non avec cela. jQuery dépend bien sûr de .innerHTML, donc maintenant je cherche un framework qui dépendra des méthodes quelque peu fastidieuses qui sont autorisées. Et je peux imaginer qu'un tel framework fonctionnera plus lentement que jQuery, mais tant qu'il fonctionne assez bien, je serai heureux.

Swanny
la source
2

Voici une réponse non technique - de nombreux travaux peuvent ne pas autoriser certaines bibliothèques, telles que jQuery.

En fait, en fait, Google n'autorise jQuery dans aucun de leurs codes (ni React, car il appartient à Facebook), que vous ne saviez peut-être pas avant que l'intervieweur ne dise "Désolé, mais vous ne pouvez pas utiliser jQuery, ce n'est pas sur la liste approuvée chez XYZ Corporation ". Vanilla JavaScript fonctionne absolument partout, à chaque fois, et ne vous posera jamais ce problème. Si vous comptez sur une bibliothèque, oui, vous obtenez la vitesse et la facilité, mais vous perdez l'universalité.

En outre, en parlant d'interview, l'autre inconvénient est que si vous dites que vous devez utiliser une bibliothèque pour résoudre un problème JavaScript lors d'un quiz sur le code, cela apparaît comme si vous ne comprenez pas réellement le problème, ce qui semble un peu mauvais. Alors que si vous le résolvez en JavaScript vanille brut, cela démontre que vous comprenez et pouvez résoudre chaque partie du problème qu'ils posent devant vous.

Jack Connor
la source
1

$(this) est différent de this :

En utilisant, $(this)vous vous assurez que le prototype jQuery est transmis à l'objet.

John Green
la source