Warum wird "$ (). Ready (Handler)" nicht empfohlen?


88

Von der jQuery API-Dokumentensite fürready

Alle drei folgenden Syntaxen sind gleichwertig:

  • $ (Dokument) .ready (Handler)
  • $ (). ready (Handler) (dies wird nicht empfohlen)
  • $ (Handler)

Nach den Hausaufgaben - Lesen und Spielen mit dem Quellcode - habe ich keine Ahnung warum

$().ready(handler) 

ist nicht zu empfehlen. Die erste und dritte Möglichkeit sind genau gleich. Die dritte Option ruft die Ready-Funktion für ein zwischengespeichertes jQuery-Objekt auf mit document:

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

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

Die Ready-Funktion hat jedoch keine Interaktion mit dem Selektor der ausgewählten Knotenelemente. Der readyQuellcode:

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

Wie Sie sehen können, wird der Rückruf nur zu einer internen Warteschlange ( readyList) hinzugefügt und die Elemente in der Gruppe werden nicht geändert oder verwendet. Auf diese Weise können Sie die readyFunktion für jedes jQuery-Objekt aufrufen .

Mögen:

  • regulärer Selektor: $('a').ready(handler) DEMO
  • Nonsense- Selektor: $('fdhjhjkdafdsjkjriohfjdnfj').ready(handler) DEMO
  • Undefinierter Selektor: $().ready(handler) DEMO

Zum Schluss ... zu meiner Frage: Warum $().ready(handler)wird das nicht empfohlen?


60
@ChaosPandion: Mir scheint, er bemüht sich, die Werkzeuge, die er verwendet, wie seinen Handrücken zu verstehen. Ich würde das nicht als vergebliche Anstrengung bezeichnen.
Jon

5
Gute Frage. Wenn jemand interessiert ist, hier ein Leistungsvergleich ... der zeigt (zumindest in Chrome), dass die "nicht empfohlene" Version tatsächlich am schnellsten ist.
James Allardice

5
Eine bessere Frage ist, warum diese überhaupt existieren. Es sollte ( $.readyzum Beispiel) eine statische Methode sein und nicht erst das Erstellen eines jQuery-Objekts erfordern.
Esailija

2
@Esailija macht den besten Punkt von allen. Sofern jQuery nicht vorhat, .ready()Funktionen für einzelne Elemente bereitzustellen , sollte es keinen Grund geben, ein jQuery-Objekt zu erstellen.

2
@ChaosPandion. Sie können das nicht verwenden ... $.readywird bereits von einer internen jQuery-Funktion übernommen, suchen Sie den Quellcode nach ready:.
Gdoron unterstützt Monica

Antworten:


88

Ich habe eine offizielle Antwort von einem der jQuery-Entwickler erhalten:

$().ready(fn)funktioniert nur, weil es $()früher eine Verknüpfung zu $(document) (jQuery <1.4) war.
Also $().ready(fn)war ein lesbarer Code.

Aber die Leute machten Dinge wie $().mouseover()und alle möglichen anderen Wahnsinns.
und die Leute mussten tun $([]), um ein leeres jQuery-Objekt zu erhalten

Also haben wir es in 1.4 geändert, sodass $()eine leere jQuery entsteht, und wir haben einfach $().ready(fn)gearbeitet, um nicht viel Code zu beschädigen

$().ready(fn) ist jetzt buchstäblich nur im Kern gepatcht, damit es für den Legacy-Fall richtig funktioniert.

Der beste Ort für die readyFunktion ist $.ready(fn), aber es ist eine wirklich alte Designentscheidung und das ist es, was wir jetzt haben.


Ich fragte ihn:

Denken Sie, dass $ (fn) besser lesbar ist als $ (). Ready (fn) ?!

Seine Antwort war:

Ich mache immer $ (document) .ready (fn) in tatsächlichen Apps und normalerweise gibt es nur einen doc ready Block in der App, es ist nicht gerade wie eine Wartungssache.

Ich denke, $ (fn) ist auch ziemlich unlesbar , es ist nur eine Sache, die man wissen muss Works ™ ...


1
Sinnvoll, jQuery nimmt die Abwärtskompatibilität ziemlich ernst
Esailija

@Esailija: Wenn sie so ernst wären, würde sie nicht das Verhalten von Switched $()an erster Stelle (wie doof wie das Verhalten gewesen sein mag) . Auf der anderen Seite hast du recht. Sie sind nicht immer so geneigt, wichtige Änderungen vorzunehmen, wie gezeigt wurde, als sie versuchten, Änderungen vorzunehmen, und .attr()einige Tage später schnell zurückgingen. Dies hat sie an einige ihrer unglücklichen frühen (und mittleren) Designentscheidungen gebunden.

3
@gdoron +1, um es direkt aus dem Maul des Pferdes zu bekommen.

2
@gdoron +1 für die richtige Antwort. Und ja, wir waren in unseren Wahrnehmungen ziemlich nahe.
VisioN

" Es ist nur eine Sache, die Sie kennen müssen Works ™ ..." Nun, $(selector[, context])und $(html[, ownerDocument]). In der Tat können Sie es genauso gut verwenden, jQuery()anstatt $()zu wissen, ob es darum geht, zu wissen, dass es funktioniert. Oder warum überhaupt jQuery verwenden?
JAB

11

Da die verschiedenen Optionen fast dasselbe bewirken, wie Sie hervorheben, ist es an der Zeit, den Hut des Bibliotheksschreibers aufzusetzen und einige Vermutungen anzustellen.

  1. Vielleicht möchten die jQuery-Leute $()für die zukünftige Verwendung zur Verfügung haben (zweifelhaft, da $().readydokumentiert ist, dass es funktioniert, auch wenn es nicht empfohlen wird; es würde auch die Semantik verschmutzen, $wenn es sich um ein spezielles Gehäuse handelt).

  2. Ein viel praktischerer Grund: Die zweite Version ist die einzige, die nicht verpackt wird document, sodass sie bei der Pflege des Codes leichter zu brechen ist. Beispiel:

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

    Vergleichen Sie dies mit

    // BEFORE
    $().ready(foo);
    
    // AFTER: breaks
    $().ready(foo).on("click", "a", function() {});
  3. Im Zusammenhang mit dem oben readyGesagten: Ist ein Freak in dem Sinne, dass es (die einzige?) Methode ist, die unabhängig davon, was das jQuery-Objekt umschließt, gleich funktioniert (auch wenn es nichts umschließt, wie dies hier der Fall ist). Dies ist ein wesentlicher Unterschied zur Semantik anderer jQuery-Methoden. Daher wird zu Recht davon abgeraten, sich speziell darauf zu verlassen.

    Update: Wie Esailijas Kommentar hervorhebt, sollte aus technischer Sicht readyeine statische Methode sein, gerade weil sie so funktioniert.

Update Nr. 2: Das Graben an der Quelle scheint irgendwann im 1.4-Zweig $()geändert worden zu sein $([]), während es sich in 1.3 so verhalten hat $(document). Diese Änderung würde die obigen Rechtfertigungen verstärken.


Ich habe noch nie einen $(document).ready( function(){ //your code here } );
solchen

Ich konnte das zweite Update nicht verstehen. Können Sie bitte noch etwas näher darauf eingehen? Ich habe nach älteren Versionen gesucht, konnte jedoch keinen Unterschied für dieses leere jQuery-Objektproblem feststellen.
Gdoron unterstützt Monica

@gdoron: Ich meine den Wechsel von selector = selector || documentzu if(!selector) return this.
Jon

4

Ich würde sagen, es ist einfach die Tatsache, dass $()ein leeres Objekt zurückgegeben wird, während Sie $(document)sich nicht ready()auf verschiedene Dinge beziehen. es funktioniert immer noch, aber ich würde sagen, es ist nicht intuitiv.

$(document).ready(function(){}).prop("title") // the title
$().ready(function(){}).prop("title")  //null - no backing document

1
Ja, die gleichen Wahrnehmungen sind in dieser Antwort . Die Änderungen fanden also in Version 1.4 statt, in der neue Rückgaberichtlinien veröffentlicht wurden.
VisioN

Ich habe noch nie jemanden gesehen, der den Dokumenttitel geändert hat, während er einen Rückruf angehängt hat . Und Sie können dies einfach mit vanilla js ohne jQuery tun . Ich sage nicht, dass es nicht die Antwort sein könnte, aber es ist kein guter Grund.
Gdoron unterstützt Monica

Nun, keine Dokumenteigenschaften oder -methoden können über$()
Alex K.

2
@AlexK. Sein Punkt war, dass niemand in Wirklichkeit tatsächlich Ketten hinter sich hat, .readyweil es eine gut etablierte Redewendung ist, dies nicht zu tun. Sicher, es gibt eine theoretische Chance, dass jemand dies tut, aber ich habe noch nie Code gesehen, der das tut (was kein gutes Argument ist, aber Sie wissen: D).
Esailija

2
Vielleicht , weil dieser theoretische Chance Methode wird nicht empfohlen , da es ein unterschiedliches Verhalten in verschiedenen Versionen hat.
VisioN

3

Höchstwahrscheinlich handelt es sich nur um einen Dokumentationsfehler, der behoben werden sollte. Der einzige Nachteil bei der Verwendung $().ready(handler)ist die Lesbarkeit. Sicher, argumentieren Sie, dass $(handler)das genauso unlesbar ist. Ich stimme zu, deshalb benutze ich es nicht .

Sie können auch argumentieren, dass eine Methode schneller ist als eine andere. Wie oft rufen Sie diese Methode jedoch oft genug hintereinander auf einer einzelnen Seite auf, um einen Unterschied festzustellen?

Letztendlich kommt es auf die persönlichen Vorlieben an. Die Verwendung eines $().ready(handler)anderen als des Lesbarkeitsarguments hat keinen Nachteil . Ich denke, die Dokumentation ist in diesem Fall falsch.


+1! Du hattest absolut recht! Sie werden es lieben, die offizielle Antwort von jQuery zu lesen. Ich habe es als Antwort hinzugefügt.
Gdoron unterstützt Monica

2

Nur um deutlich zu machen, dass die drei inkonsistent sind, habe ich die vierte häufig verwendete Form hinzugefügt: (function($) {}(jQuery));

Mit diesem Markup:

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

und dieser 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);
});

Die angezeigten Ergebnisse des div aus der letzten Anweisung sind: 0: 9: 9: 9: undefiniert

SO, nur die Handler- und Doc-Versionen stimmen mit der jQuery-Konvention überein, etwas Nützliches zurückzugeben, wenn sie die Dokumentauswahl erhalten, und mit dem übergebenen Formular müssen Sie etwas zurückgeben (ich würde das nicht tun, würde ich denken, aber es einfach einfügen "innen" zu zeigen hat etwas).

Hier ist eine Geigenversion davon für Neugierige: http://jsfiddle.net/az85G/


Ich kann nicht sehen, woran es liegt, dass nichts gefunden wird. Der Kontext, den Sie für die jQuery angegeben haben, lautet nullalso .find('*').lengthreturn 0 . Finden Sie etwas Schlechtes an diesem (offensichtlichen) Verhalten?
Gdoron unterstützt Monica

@gdoron - Ich finde an diesem Verhalten nichts Schlechtes. Ich wollte nur auf den Unterschied hinweisen, wenn es einen Selektor gibt, der NICHT null ist. Beachten Sie, dass dieser leere Selektor wahrscheinlich der Grund ist, warum die "schnelleren" Kommentare notiert werden an anderer Stelle, da ein kleineres Objekt verarbeitet werden muss, aber DOES ein Objekt zurückgibt und in diesem Fall nicht "undefiniert" ist. Ich mag die Frage wirklich und habe sie positiv bewertet :)
Mark Schultheiss

Der Grund dafür ist, dass es schneller ist, weil die erste "Unterbrechungs" -Zustand des Ctors ist, if(!selector) return thiswenn Sie etwas anderes geben, gibt es regexund andere Dinge, die vor sich gehen ... Danke für freundliche Worte ... Ich denke, ich könnte das jQuery-Team darum bitten Antworte darauf (verdammt, es ist nicht meine Bibliothek :-)).
Gdoron unterstützt Monica

Ja, ich habe diesen bestimmten Teil der Codebasis nicht studiert, ich habe den Kern gehackt, um Interum-Fixes für Fehler einzufügen, aber nicht diesen Teil davon. Ich bevorzuge es jQuery(document).ready(function(){});derzeit, das Formular in unserer Codebasis zu sehen, da es unterschiedliche Ebenen von jQuery-Fachwissen gibt und es für neue Leute "am offensichtlichsten" ist, dass es sich um eine Event-Handler-Funktion für jQuery handelt.
Mark Schultheiss

0

Ich denke, das ist wirklich mehr für die Lesbarkeit als alles andere.

Dieser ist nicht so ausdrucksstark

$().ready(handler);

wie

$(document).ready(handler)

Vielleicht versuchen sie, irgendeine Form von idiomatischer jQuery zu fördern.


3
$(document).ready(handler)ist lesbarer als $(handler)empfohlen wird ...
Gdoron unterstützt Monica
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.