2013-03-09 16 views
8

Wie würde jQuery seinen Konstruktor erlauben, als eine Funktion zu fungieren, die Argumente akzeptiert, während sein Konstruktor auch als eine Funktion fungiert, die Argumente annimmt?jQuery Prototyp und Konstruktor Funktion Verkettung

Ich bin ein wenig neu in JavaScript, also entschuldigen Sie, wenn dies eine noob Frage ist, (Ich habe die Quelle angeschaut, aber es ist schwer zu sezieren).

Wie auch immer, als Beispiel $(document).ready(<args>); Sowohl der Konstruktor $() und der Prototyp ready() Akt als eine Funktion. Wie? Denn wenn ich dies versuchen:

var $ = function(selector) { 
    if(selector == document) { 
     return document; 
    } 
}; 

$.prototype = { 
    constructor: $, 
    ready: function(args) { 
     if(isDomReady) { 
      args.apply(document); 
     } else { 
      window.onload = args; 
     } 
    } 
}; 

var isDomReady = (document.addEventListener || document.readyState == ("complete"|"loaded"|true|4) || document.onreadystatechange()) ? true : false; 

$(document).ready(function() { alert("Wibbles!") }); 

ich einen Fehler Uncaught Typeerror erhalten: Object [global Objekt] hat keine Methode 'ready'

+0

Sie verketten die Methoden nicht, indem Sie 'this' von' ready' zurückgeben. –

+1

Ich weiß, warum Sie die Fehlermeldung erhalten. Das $ (Dokument) gibt nur das HTMLDocument zurück, das keine .ready Funktion hat. Wenn $ eine "Element" -Eigenschaft hat, die das Dokumentelement beim Ausführen des Konstruktors speichert, dann könnten Sie den Bereit-Status überprüfen, indem Sie auf das gespeicherte Element in der Ready-Funktion zugreifen. – MattDiamant

+0

@MattDiamant Ahh ... Ich denke, ich werde diesen Kommentar noch ein paar Mal für das Studium lesen. Lol. Aber ich denke ich verstehe. Vielen Dank. –

Antwort

8

Wissen Sie, das fasziniert mich ganz. Du hast bereits eine Antwort angenommen, aber lass mich einfach meine veröffentlichen, falls es sich als nützlich erweist. Es gibt eine fiddle created here

jQuery = function(selector, context) { 
    // The jQuery object is actually just the init constructor 'enhanced' 
    return new jQuery.fn.init(selector, context); 
}; 

jQuery.fn = jQuery.prototype = { 
    constructor: jQuery, 
    context: null, 
    isReady: null, 
    init: function(selector, context) { 
     if (selector === document){ 
      this.context = document; 
      this.selector = document; 
     } 
     console.log(this); 
     return this; 
    }, 
    ready: function(func){ 
     var args = Array.prototype.slice.call(this, arguments), 
      boundReadyFunc = func.bind(this, args.slice(1)); 

     if (this.isReady){ 
      func(); 
     } 
     else { 
      document.addEventListener("DOMContentLoaded", this.onReady.bind(this, func), false); 
     } 
    }, 
    onReady: function(func){ 
     console.log("onready"); 
     this.isReady = true; 
     func.call(this); 
    }, 
}; 

jQuery.fn.init.prototype = jQuery.fn; 
jQuery(document).ready(function(){ 
    alert("Hey, here I am"); 
}); 

Lassen Sie mich versuchen zu erklären, wie das funktioniert.

Jedes Mal, wenn Sie etwas wie $(selector) aufrufen, wird eine neue jQuery-Instanz mit den von Ihnen bereitgestellten Optionen erstellt (siehe return new jQuery.fn.init(selector, context););

Der Einfachheit halber stellen wir den jQuery-Prototyp als einen anderen globalen Namen, jQuery.fn. Um es wirklich verkettbar zu machen, muss die init Funktion eine neue jQuery Instanz zurückgeben. Aus diesem Grund definieren wir am Ende explizit, dass die Prototypen für beide jQuery und jQuery.init identisch sind. Auf diese Weise können Sie jetzt Funktionsaufrufe wie

verknüpfen. Hoffe, das hilft.

Sie können die jQuery-Quelle auch unter github finden. Es ist modular und sehr einfach zu folgen.

+0

Danke! Das ist mehr von der Richtung, nach der ich gesucht habe, aber es kam ein bisschen spät, ich bin bereits in die Funktionsketten eingedrungen. Trotzdem danke! –