Pourquoi "$ (). Ready (handler)" n'est pas recommandé?

88

Depuis le site de documentation de l'API jQuery pourready

Les trois syntaxes suivantes sont équivalentes:

  • $ (document) .ready (gestionnaire)
  • $ (). ready (handler) (ce n'est pas recommandé)
  • $ (gestionnaire)

Après avoir fait mes devoirs - lire et jouer avec le code source , je ne sais pas pourquoi

$().ready(handler) 

n'est pas recommandé. Les première et troisième méthodes sont exactement les mêmes, la troisième option appelle la fonction ready sur un objet jQuery mis en cache avec document:

rootjQuery = jQuery(document);
...
...

// HANDLE: $(function)
// Shortcut for document ready
} else if ( jQuery.isFunction( selector ) ) {
    return rootjQuery.ready( selector );
}

Mais la fonction ready n'a aucune interaction avec le sélecteur des éléments de nœud sélectionnés, Le readycode source:

ready: function( fn ) {
    // Attach the listeners
    jQuery.bindReady();
        // Add the callback
    readyList.add( fn );
        return this;
},

Comme vous pouvez le voir, il Justs ajouter le rappel à une file d' attente interne ( readyList) et ne change pas ou utiliser les éléments dans l'ensemble. Cela vous permet d'appeler la readyfonction sur chaque objet jQuery.

Comme:

  • sélecteur régulier : $('a').ready(handler) DEMO
  • Sélecteur absurde : $('fdhjhjkdafdsjkjriohfjdnfj').ready(handler) DEMO
  • Indéfini sélecteur: $().ready(handler) DEMO

Enfin ... à ma question: pourquoi $().ready(handler)n'est pas recommandé?

gdoron soutient Monica
la source
60
@ChaosPandion: Pour moi, il semble qu'il s'efforce de comprendre les outils qu'il utilise comme le dos de sa main. Je n'appellerais pas exactement cela un effort inutile.
Jon
5
Bonne question. Si quelqu'un est intéressé, voici une comparaison des performances ... qui montre (au moins dans Chrome) que la version "non recommandée" est en fait la plus rapide.
James Allardice
5
Une meilleure question est de savoir pourquoi ceux-ci existent même, cela devrait être une méthode statique ( $.readypar exemple) et ne pas nécessiter la construction d'un objet jQuery en premier lieu.
Esailija
2
@Esailija fait valoir le meilleur de tous. À moins que jQuery ne prévoie de fournir une sorte de .ready()capacité pour des éléments individuels, il ne devrait y avoir aucune raison de construire un objet jQuery.
2
@ChaosPandion. Vous ne pouvez pas utiliser cela ... $.readyest déjà pris par une fonction jQuery interne, recherchez le code source ready:.
gdoron soutient Monica

Réponses:

88

J'ai eu une réponse officielle de l'un des développeurs jQuery:

$().ready(fn)fonctionne uniquement parce que $()c'était un raccourci vers $(document) (jQuery <1.4)
Il en $().ready(fn)était de même pour un code lisible.

Mais les gens faisaient des choses comme $().mouseover()et toutes sortes d'autres folies.
et les gens ont dû faire $([])pour obtenir un objet jQuery vide

Donc en 1.4 nous l'avons changé donc $()donne un jQuery vide et nous avons juste fait le $().ready(fn)travail pour ne pas casser beaucoup de code

$().ready(fn) est littéralement maintenant juste patché dans le noyau pour le faire fonctionner correctement pour le cas hérité.

Le meilleur endroit pour la readyfonction est $.ready(fn), mais c'est une décision de conception vraiment ancienne et c'est ce que nous avons maintenant.


Je lui ai demandé:

Pensez-vous que $ (fn) est plus lisible que $ (). Ready (fn)?!

Sa réponse a été:

Je fais toujours $ (document) .ready (fn) dans les applications réelles et il n'y a généralement qu'un seul bloc doc ready dans l'application, ce n'est pas exactement comme une opération de maintenance.

Je pense que $ (fn) est assez illisible aussi , c'est juste une chose que vous devez savoir fonctionne ™ ...

gdoron soutient Monica
la source
1
Cela a du sens, jQuery est assez sérieux au sujet de la compatibilité ascendante
Esailija
@Esailija: S'ils étaient aussi sérieux, ils n'auraient pas changé de comportement $()en premier lieu (aussi maladroit que ce comportement ait pu être) . D'un autre côté, vous avez raison. Ils ne sont pas toujours aussi enclins à faire des changements de rupture, comme cela a été montré lorsqu'ils ont essayé de changer .attr(), puis ils ont fait un retour rapide quelques jours plus tard. Cela les a liés à certaines de leurs malheureuses décisions de conception au début (et à la quarantaine).
3
@gdoron +1 pour l'avoir obtenu directement de la bouche du cheval.
2
@gdoron +1 pour obtenir la vraie réponse. Et, oui, nous avons été assez proches dans nos perceptions.
VisioN
" c'est juste une chose que vous devez savoir fonctionne ™ ..." Eh bien aussi $(selector[, context])et $(html[, ownerDocument]). En fait, vous pouvez tout aussi bien utiliser jQuery()plutôt que $()si avoir à savoir que cela fonctionne est le problème. Ou pourquoi même utiliser jQuery?
JAB
11

Étant donné que les différentes options font à peu près la même chose que vous le faites remarquer, il est temps de mettre le chapeau d'écrivain de la bibliothèque et de faire des suppositions.

  1. Peut-être que les gens de jQuery aimeraient avoir $()disponible pour une utilisation future (douteux car il $().readyest documenté pour fonctionner, même s'il n'est pas recommandé; cela polluerait également la sémantique de la $casse spéciale).

  2. Une raison beaucoup plus pratique: la deuxième version est la seule qui ne finit pas par s'emballer document, il est donc plus facile de casser lors de la maintenance du code. Exemple:

    // BEFORE
    $(document).ready(foo);
    
    // AFTER: works
    $(document).ready(foo).on("click", "a", function() {});
    

    Comparez cela avec

    // BEFORE
    $().ready(foo);
    
    // AFTER: breaks
    $().ready(foo).on("click", "a", function() {});
    
  3. Lié à ce qui précède: readyest un phénomène dans le sens où c'est (la seule?) Méthode qui fonctionnera de la même manière, peu importe ce que l'objet jQuery enveloppe (même s'il n'enveloppe rien comme c'est le cas ici). C'est une différence majeure par rapport à la sémantique des autres méthodes jQuery, il est donc déconseillé de s'y fier à juste titre.

    Mise à jour: Comme le souligne le commentaire d'Esailija, du point de vue de l'ingénierie, cela readydevrait vraiment être une méthode statique, exactement parce que cela fonctionne comme ça.

Mise à jour n ° 2: En creusant à la source, il semble qu'à un moment donné, la branche 1.4 a $()été modifiée pour correspondre $([]), tandis que dans la version 1.3, elle s'est comportée comme $(document). Ce changement renforcerait les justifications ci-dessus.

Jon
la source
Je n'ai jamais vu de code comme celui-ci, le vieil idiome était$(document).ready( function(){ //your code here } );
Esailija
Je n'ai pas compris la deuxième mise à jour, pouvez-vous en dire plus s'il vous plaît? J'ai recherché des versions plus anciennes, mais je n'ai trouvé aucune différence pour ce problème d'objet jQuery vide.
gdoron soutient Monica
@gdoron: Je veux dire le changement de selector = selector || documentà if(!selector) return this.
Jon
4

Je dirais que c'est simplement le fait que $()retourne un objet vide , alors que ce $(document)n'est pas le cas de votre application ready()à des choses différentes; cela fonctionne toujours, mais je dirais que ce n'est pas intuitif.

$(document).ready(function(){}).prop("title") // the title
$().ready(function(){}).prop("title")  //null - no backing document
Alex K.
la source
1
Oui, les mêmes perceptions sont dans cette réponse . Les changements ont donc eu lieu dans la version 1.4, qui a publié une nouvelle politique de retour.
VisioN
Je n'ai jamais vu quelqu'un changer le titre du document tout en attachant un rappel prêt, et vous pouvez simplement le faire avec vanilla js sans jQuery . Je ne dis pas que ce n'est peut-être pas la réponse, mais ce n'est pas une bonne raison.
gdoron soutient Monica
Eh bien, aucune propriété ou méthode de document ne peut être chaînée via$()
Alex K.
2
@AlexK. son argument était que personne en réalité n'enchaîne réellement après .readyparce que c'est un idiome bien établi de ne pas le faire. Bien sûr, il y a une chance théorique que quelqu'un fasse cela, mais je n'ai jamais vu de code faire cela (ce qui n'est pas un bon argument mais vous savez: D).
Esailija
2
Peut-être à cause de cette méthode aléatoire théorique n'est pas recommandée , car elle a un comportement différent dans différentes versions.
VisioN
3

Plus que probablement, il ne s'agit que d'un bogue de documentation et devrait être corrigé, le seul inconvénient de l'utilisation $().ready(handler)est sa lisibilité. Bien sûr, soutenez que $(handler)c'est tout aussi illisible. Je suis d'accord, c'est pourquoi je ne l'utilise pas .

Vous pouvez également affirmer qu'une méthode est plus rapide qu'une autre. Cependant, à quelle fréquence appelez-vous cette méthode suffisamment de fois de suite sur une seule page pour remarquer une différence?

En fin de compte, cela dépend de vos préférences personnelles. Il n'y a aucun inconvénient à utiliser $().ready(handler)autre que l'argument de lisibilité. Je pense que la documentation manque de précision dans ce cas.

Kevin B
la source
+1! Vous aviez absolument raison! Vous allez adorer lire la réponse officielle de jQuery. Je l'ai ajouté comme réponse.
gdoron soutient Monica
2

Juste pour rendre évident qu'il y a une certaine incohérence dans les trois, j'ai ajouté le quatrième formulaire souvent utilisé: (function($) {}(jQuery));

Avec ce balisage:

<div >one</div>
<div>two</div>
<div id='t'/>

et ce code:

var howmanyEmpty = $().ready().find('*').length;
var howmanyHandler = $(function() {}).find('*').length;
var howmanyDoc = $(document).ready().find('*').length;
var howmanyPassed = (function($) { return $('*').length; }(jQuery));
var howmanyYuck = (function($) {}(jQuery));
var howmanyYuckType = (typeof howmanyYuck);

$(document).ready(function() {
    $('#t').text(howmanyEmpty + ":" + howmanyHandler + ":" 
        + howmanyDoc + ":" + howmanyPassed + ":" + howmanyYuckType);
});

Les résultats affichés du div de la dernière instruction sont: 0: 9: 9: 9: undefined

SO, seules les versions Handler et Doc sont cohérentes avec la convention jQuery de renvoyer quelque chose d'utile lorsqu'ils obtiennent le sélecteur de document et avec le formulaire Passed, vous devez retourner quelque chose (je ne le ferais pas je pense, mais mettez-le simplement pour montrer "à l'intérieur" il y a quelque chose).

En voici une version violon pour les curieux: http://jsfiddle.net/az85G/

Mark Schultheiss
la source
Je ne vois pas quel est le problème avec le fait qu'il ne trouve rien, le contexte que vous avez donné pour jQuery est nulldonc de .find('*').lengthretour 0 . Trouvez-vous quelque chose de mauvais avec ce comportement (évident)?
gdoron soutient Monica
@gdoron - Je ne trouve rien de mal à ce comportement, je voulais juste souligner la différence par rapport au moment où il a un sélecteur qui n'est PAS nul - notez que ce sélecteur vide est probablement la raison pour laquelle les commentaires "plus rapides" sont notés ailleurs car il a un objet plus petit à traiter, mais renvoie un objet et non "indéfini" dans cette instance. J'aime vraiment la question et je l'ai votée :)
Mark Schultheiss
La raison en est que c'est plus rapide, parce que la première condition de "rupture" du ctor est que if(!selector) return thissi vous donnez autre chose, il y a regexet d'autres choses qui se passent ... Merci pour vos aimables paroles ... Je pense que je pourrais demander à l'équipe jQuery de répondez à ceci (bon sang, ce n'est pas ma bibliothèque :-)).
gdoron soutient Monica
Oui, je n'ai pas étudié cette partie particulière de la base de code, j'ai piraté le noyau pour mettre en place des correctifs interum pour les bogues mais pas cette partie. Je préfère voir le jQuery(document).ready(function(){});formulaire dans notre base de code pour le moment car il existe différents niveaux d'expertise jQuery et il est "le plus évident" pour les nouveaux venus que c'est une fonction de gestionnaire d'événements pour jQuery.
Mark Schultheiss
0

Je pense que c'est vraiment plus pour la lisibilité qu'autre chose.

Celui-ci n'est pas aussi expressif

$().ready(handler);

comme

$(document).ready(handler)

Peut-être essaient-ils de promouvoir une forme de jQuery idiomatique.

Hyangelo
la source
3
$(document).ready(handler)est plus lisible que $(handler)ce qui est recommandé ...
gdoron soutient Monica