56 votes

Quel est le coût de "$(this)" ?

Les gens ici suggèrent souvent de mettre en cache le jQuery créé à partir d'un objet DOM comme dans ce code :

$('#container input').each(function() {
    $(this).addClass('fooClass');
    $(this).attr('data-bar', "bar");
    $(this).css('background-color', 'red');
});
  • La mise en cache de l'objet jQuery améliore-t-elle réellement les performances de notre code ?
  • Que se passe-t-il "en coulisses" lorsque vous passez un élément DOM au constructeur jQuery ?

53voto

gdoron Points 61066

Dans l'application jQuery info sur les étiquettes cet avertissement apparaît :

La fonction jQuery $() est coûteuse. L'appeler à plusieurs reprises est extrêmement inefficace.

Eh bien... cela n'est vrai que pour les sélecteurs de chaînes, qui sont analysés avec des expressions rationnelles pour savoir ce qu'ils sont :

quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/

Ensuite, si la chaîne est un sélecteur (autre que id ), jQuery parcourt le DOM pour trouver une correspondance avec sa coûteuse fonction find fonction :

} else if ( !context || context.jquery ) {
    return ( context || rootjQuery ).find( selector );
}

Alors oui, c'est cher, mais ce n'est vrai que pour les sélecteurs !

Si nous passons un DOMElement La seule action de jQuery consiste à enregistrer le paramètre DOMElement en tant que contexte de l'objet jQuery nouvellement créé et à fixer la longueur du contexte à 1 :

// Handle $(DOMElement)
if ( selector.nodeType ) {
    this.context = this[0] = selector; // Selector here is a DOMElement
    this.length = 1;
    return this;
}

Je l'ai fait quelques tests avec jsPerf et j'ai constaté que la mise en cache de l'objet jQuery n'avait qu'un effet limité :

Bar chart, described below

Dans Chrome, le ralentissement n'est que de 7 %. (Dans IE, c'est un peu plus important : 12 %).

14voto

SLaks Points 391154

Pour répondre à votre deuxième question, regardez le source :

// Handle $(DOMElement)
if ( selector.nodeType ) {
    this.context = this[0] = selector;
    this.length = 1;
    return this;
}

10voto

cliffs of insanity Points 2145

En ce qui concerne la différence de performance, si vous cherchez une comparaison directe entre les deux, il est utile de supprimer tout code supplémentaire qui pourrait fausser le résultat, comme la sélection DOM et d'autres méthodes qui ne sont pas directement liées.

http://jsperf.com/this-cost/2

enter image description here

Dans un contexte plus réel, la différence relative est mineure, comme l'a montré votre test.

Une autre chose à garder à l'esprit est que chaque fois que vous créez un objet jQuery, de la mémoire doit lui être allouée, ce qui ajoute au travail que le garbage collector doit effectuer.

Je pense donc que la raison pour laquelle les gens suggèrent la mise en cache est en quelque sorte une question de principe. Un travail supplémentaire est effectué qui, bien qu'il n'ait généralement pas d'impact notable, nécessite en fin de compte des frais généraux qui peuvent être facilement évités.

8voto

josh3736 Points 41911

Tous les tests de performance en cours d'exécution ne tiennent pas compte d'un autre élément important :

Largeur de bande du réseau.

Mise en cache $(this) dans une variable locale diminuera généralement la taille de votre script, en particulier lorsqu'il est minifié (parce que this ne peut être réduit à partir de quatre caractères).

Envisager :

function hello(text) {
    $(this).attr();
    $(this).css();
    $(this).data();
    $(this).click();
    $(this).mouseover();
    $(this).mouseleave();
    $(this).html(text);
}
hello('Hello world');

Le résultat minifié du compilateur de fermeture est le suivant

function hello(a){$(this).attr();$(this).css();$(this).data();$(this).click();$(this).mouseover();$(this).mouseleave();$(this).html(a)}hello("Hello world");

Cela permet d'économiser 39 octets (20 %). Considérons maintenant :

function hello(name) {
    var $this = $(this);
    $this.attr();
    $this.css();
    $this.data();
    $this.click();
    $this.mouseover();
    $this.mouseleave();
    $this.html(name);
}
hello('Hello world');

Le résultat de la minification est le suivant

function hello(b){var a=$(this);a.attr();a.css();a.data();a.click();a.mouseover();a.mouseleave();a.html(b)}hello("Hello world");

Cela permet d'économiser 74 octets (37 %), ce qui double presque notre économie d'octets. Il est évident que les économies réalisées dans le monde réel pour les grands scripts seront moindres, mais la mise en cache vous permettra de réduire considérablement la taille de vos scripts.

En réalité, la mise en cache n'a que des avantages $(this) . Vous obtenez des gains de performance minuscules mais mesurables. Plus important encore, vous pouvez réduire le nombre d'octets qui transitent sur le câble, et ce qui se traduit directement par plus d'argent parce que un chargement plus rapide des pages se traduit par une augmentation des ventes .

Si l'on considère les choses sous cet angle, on peut dire qu'il y a une coût en dollars à la répétition $(this) et ne pas le mettre en cache.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X