Differenza del valore, prototipo e proprietà

OK! Prima di tutto questa domanda viene da un uomo che scava troppo in profondità (e si può eventualmente perdere) nell’universo jQuery.

Nella mia ricerca ho scoperto che lo schema principale di jquery è simile a questo (se necessario, la correzione è corretta):

(function (window, undefined) { jQuery = function (arg) { // The jQuery object is actually just the init constructor 'enhanced' return new jQuery.fn.init(arg); }, jQuery.fn = jQuery.prototype = { constructor: jQuery, init: function (selector, context, rootjQuery) { // get the selected DOM el. // and returns an array }, method: function () { doSomeThing(); return this; }, method2: function () { doSomeThing(); return this;, method3: function () { doSomeThing(); return this; }; jQuery.fn.init.prototype = jQuery.fn; jQuery.extend = jQuery.fn.extend = function () { //defines the extend method }; // extends the jQuery function and adds some static methods jQuery.extend({ method: function () {} }) }) 

Quando $ avvia jQuery.prototype.init avvia e restituisce una matrice di elementi. Ma non ho capito come aggiunge il metodo jQuery come .css o .hide , ecc. a questo array.

Ottengo i metodi statici. Ma non è ansible ottenere come restituisce e matrice di elementi con tutti quei metodi.

Non mi piace neanche quello schema. Hanno una funzione init , che è il costruttore di tutte le istanze di jQuery – la stessa funzione jQuery è solo un involucro attorno alla creazione di un object con new :

 function jQuery(…) { return new init(…); } 

Quindi, aggiungono i metodi di tali istanze all’object init.prototype . Questo object è esposto come interfaccia su jQuery.fn . Inoltre, impostano la proprietà prototype della funzione jQuery su quell’object – per coloro che non utilizzano la proprietà fn . Ora hai

 jQuery.prototype = jQuery.fn = […]init.prototype 

Ma fanno anche due cose [strane]:

  • sovrascrivere la proprietà del constructor dell’object prototype, impostandola sulla funzione jQuery
  • esponendo la funzione init su jQuery.fn – il suo prototipo. Ciò potrebbe consentire l’ estensione della funzione $ .fn.init , ma è molto confuso

Penso che abbiano bisogno / voglia di fare tutto ciò per essere infallibili, ma il loro codice è un disastro – iniziando con quell’object letterale e assegnando le cose del prototipo di init in seguito.

È più facile da digerire se pensi che l’API sia una raccolta di metodi esterna e la funzione jQuery come wrapper.

È fondamentalmente costruito in questo modo:

 function a() { return new b();} a.prototype.method = function() { return this; } function b() {} b.prototype = a.prototype; 

Tranne che a è jQuery b è jQuery.prototype.init .

Sono sicuro che Resig aveva le sue ragioni per posizionare il costruttore di api nel prototipo di init, ma non riesco a vederle. Un paio di stranezze oltre a quelle menzionate da Bergi:

1) I pattern richiedono una copia di riferimento da jQuery.fn.init.prototype a jQuery.prototype , che consente uno strano loop infinito:

 var $body = new $.fn.init.prototype.init.prototype.init.prototype.init('body'); 

2) Ogni collezione jQuery è in realtà un’istanza di jQuery.fn.init , ma dal momento che fanno riferimento allo stesso object prototipo, ci jQuery.fn.init a “pensare” che la raccolta sia un’istanza di jQuery . Puoi fare la stessa stregoneria in questo modo:

 function a(){} function b(){} a.prototype = b.prototype; console.log( new b instanceof a); // true console.log( new a instanceof b); // true 

Sidenote: ho utilizzato personalmente il seguente schema di costruzione con risultati simili senza la stranezza:

 var a = function(arg) { if (!(this instanceof a)) { return new a(arg); } }; a.prototype.method = function(){ return this; };