2011-10-04 13 views
6

All'inizio pensavo di assegnare obj [0], obj [1], obj [2], ecc. All'oggetto jQuery prima di restituirlo, e che la lunghezza è manualmente assegnata a. Ma no, dal momento che console.log registra una matrice e non un oggetto.In che modo jQuery crea oggetti-matrice?

Ho dato una rapida occhiata alla sorgente di jQuery ma dal momento che non ho familiarità con esso non l'ho risolto facilmente. jQuery.makeArray è comparso per primo, ma si è rivelato essere l'opposto di quello che sto cercando, in realtà perdi i metodi oggetto usandolo.

La mia prima ipotesi è di iniziare prima l'array e poi copiare tutte le proprietà e i metodi dall'oggetto.

Qualcuno con l'esperienza del codice sorgente di jQuery ha una risposta chiara a questo?

+0

È presumibilmente simile a come 'NodeList' funziona come un array ma non lo è. – BoltClock

+0

Quali oggetti di matrice? Come sai che registra un array e non un oggetto? –

risposta

5

È semplice come creare una nuova funzione e assegnarla a un nuovo array come prototipo.

function ArrayLike() {} 
ArrayLike.prototype = []; 

Così, per esempio:

function ArrayLike() {} 
ArrayLike.prototype = []; 
ArrayLike.prototype.fromArray = function(arr) { 
    for(var i = 0; i < arr.length; i++) 
     this.push(arr[i]); 
}; 
ArrayLike.prototype.foo = function() { 
    console.log("foo", this); 
}; 

var a = new ArrayLike(); 
a.fromArray([1, 2]); 
console.log(a); 
a.foo(); 

http://jsfiddle.net/Xeon06/fUgaf/

+0

Questo è straordinariamente fluido. Sto per fare una domanda su una versione minimalista di questo. Grazie. – Manngo

13

jQuery crea ciò che viene chiamato (nello standard ES) come oggetti di tipo array. In particolare, hanno una proprietà length e anche (che fa uso della proprietà length) hanno gli elementi rilevanti inseriti in indici basati su numeri interi.

E 'semplice come:

var arrayLike = {length: 3, 0:'first', 1:'second', 2:'third'}; 
Array.prototype.join.call(arrayLike, '|'); // "first|second|third" 

Se si dà un'occhiata a the standard (15.4.4), in particolare le modalità Array.prototype vedrete la seguente nota in tutti e ciascuno:

NOTA La funzione * è volutamente generica; non richiede che il suo valore sia un oggetto Array. Pertanto può essere trasferito su altri tipi di oggetti da utilizzare come metodo. Se la funzione * può essere applicata correttamente a un oggetto host dipende dall'implementazione.

Se si guarda la descrizione di questi algoritmi, hanno praticamente basta usare la proprietà length per scorrere sopra l'oggetto (nel nostro caso un oggetto array-like) e accedere ai valori dietro quelli basati interi chiavi. Per questo motivo sono generici e funzionano su oggetti js regolari con le proprietà pertinenti.

In sostanza, tutto ciò che fa jQuery (se ricordo bene l'edificio è fatto in sfrigolio, il motore di selezione css di jquery). Puoi testarlo/provarlo in vari modi. Ad esempio, Array uno standard js esegue alcune magia quando la proprietà lunghezza si accorcia, ma l'oggetto jquery no:

var arr = [1,2,3], $arr = $('div'); // assuming three divs 
arr.length=2; arr[2]; // undefined 
$arr.length=2; $arr[2]; // still references the div 

http://jsfiddle.net/cnkB9/

Quindi di makeArray jquery converte l'array come oggetto jquery e marchi in un vero array js nativo, ma come hai detto tu, non ha tutti i metodi jquery collegati.

Per quanto riguarda il motivo per cui si presenta nella console, mi riferisco a questo eccellente risposta: What makes Firebug/Chrome console treat a custom object as an array? che spiega che la presenza della proprietà length e splice funzione permettono di apparire come un array in maggior parte console. Come accennato, non è il caso della console Web di FF4, che mostra semplicemente che non è un array js nativo. È interessante notare che la funzione splice in realtà non deve funzionare, basta essere presente ed essere una funzione.Ad esempio:

>> console.log({length:2,0:'some',1:'thing',splice:new Function}); 
["some", "thing"] 
5

Il seguente semplice codice di come trasformare una matrice restituita da un selettore jQuery in funzione con un nativo array JavaScript:

var $arr = $('option'); // assuming three options 
var arr = Array.apply(null, $arr); 
// arr contains [option, option] 

Considerando il seguente codice HTML per il codice sopra:

<html> 
    <head> 
     <script type="text/javascript" src="jquery-1.5.2.min.js"></script> 
    </head> 
    <body> 
     <select id="addSelection"> 
      <option value="Original Value">Original Value</option> 
      <option value="Two Value">Value two</option> 
      <option value="Three Value">Value three</option> 
     </select> 

     <br /> 

     <input id="btn" type="button" value="Changes" /> 
    </body> 
</hmtl> 
Problemi correlati