2012-01-09 11 views
8

Ho un'altra domanda riguardante l'architettura di jQuery. $('div') costruisce un nuovo jQuery oggetto:Perché è possibile interrogare jQuery ('div') come un array?

$('div') instanceof jQuery; // true 

Mi piacerebbe sapere il motivo per cui è possibile interrogare è come un array, allthough non è un array?

$('div')[0]; // returns the first div in the document as a DOM node. 
$.isArray($('div')); // false 

Adoro questa sintassi, sembra così pulita! Ho anche notato questa restituisce i nodi DOM come un array:

console.log($('div')); 

qualcuno può spiegare come implementare questo comportamento per i miei oggetti?


Il mio approccio è stato quello di fare un array con alcuni metodi come questo:

var a = ['a', 'b', 'c']; 
a.method = function(){ return 'test'; }; 
a; // ['a', 'b', 'c'] 
a[0]; // 'a' 
a.method(); // 'test' 

Tuttavia questo non sembra essere il modo jQuery fa come questo è in realtà un array:

$.isArray(a); // true 

Mi piacerebbe sapere come jQuery fa questo per imparare e vedere se è una soluzione migliore della mia.

+0

È possibile accedere a tutta la proprietà * * utilizzando [] 'notazione'. Non solo indici. Quindi, come '$ ('div') [0]', puoi fare '$ ('div') ['jquery']', che ti darà il numero di versione di jQuery. –

+0

@amnotiam Lo so. Ma quando stampo oggetti soliti nelle console, non producono un array. –

+0

Ah, se stai chiedendo in particolare l'output della console, allora è solo la console a fare la sua ipotesi su ciò che hai dato. [j La risposta di Aman] (http://stackoverflow.com/a/8793090/1106925) mostra quali sono le console in genere. –

risposta

10

Un oggetto jQuery è ciò che noi chiamiamo Array-like object. Ciò significa che è effettivamente un oggetto "vero" (infatti, tutti gli "array" sono oggetti in ECMAscript), ma possiede certe proprietà che lo fanno apparire come una matrice "vera". Queste proprietà sono

  • come .length proprietà
  • possiede il metodo .splice()

questi due fatti sono abbastanza che la maggior parte dei motori js console saranno interpretare l'oggetto come array.

Esempio:

var myObject = { }, 
    push = Array.prototype.push; 

myObject.aNiceFunction = function() { 
    console.log(this); 
}; 

push.call(myObject, document.getElementById('foo')); 
push.call(myObject, document.getElementById('bar')); 

myObject.splice = Array.prototype.splice; 

Se ora registriamo il nostro oggetto

console.log(myObject); 

otteniamo i jQuery'ish tipici risultato

[div#foo, div#bar] 

See that in action

ma siamo ancora in grado di chiamare il nostro metodo .aNiceFunction() su quell'oggetto. Spingendo nuovi elementi con il metodo Array.prototype.push() sul nostro oggetto, ECMAscript indicizzerà automaticamente tali elementi per noi. Questa era una breve descrizione di cosa succede sotto il cofano di JQuery.

Un'altra parola su "Array" in ECMAscript. Non ci sono matrici reali in questa lingua (se ci dimentichiamo di typed arrays per un secondo). C'è solo Object. Se abbiamo un oggetto che eredita da Array.prototype lo chiameremmo quasi un array. Tutto ciò che avremmo dovuto fare è impostare la proprietà .length su 0.

+2

I motori JS non interpretano nulla come una matrice. JS _users_ interpretare le cose come array. :) – SLaks

+0

@SLaks: touchè. Quello che volevo dire è che, per esempio, è "disconnesso" dall'oggetto console. – jAndy

+0

Questa è una funzione della bella stampante di Firebug/Chrome (che sono utenti JS), non del motore JS. – SLaks

2

Gli oggetti jQuery sono oggetti a forma di array.

Un oggetto di tipo array è un oggetto ordinario con le stesse proprietà di un array.
Un array come oggetto ha una proprietà length impostata su un intero positivo, e le proprietà denominate 0, 1, ... length − 1 contenente gli oggetti array.

0

jQuery objects sono oggetti "array-like". Si consideri il seguente codice:

document.forms.length; // returns 1; 
document.forms[0]; // returns a form element. 
document.forms.join(", "); // throws a type error. this is not an array. 
typeof document.forms; // returns "object" 

Modificare il vostro codice, si potrebbe ottenere lo stesso effetto:

var a = 
{ 
    0: 'a', 
    1: 'b', 
    2: 'c', 
    length: 3, 
    method: function() { 
     return "test"; 
    } 
}; 
+0

'console.log (a)' stampa l'oggetto non la matrice. Quindi questo non sembra essere il modo in cui lo fa jQuery. E dal modo in cui non sono un principiante di JavaScript, so come funzionano gli oggetti JavaScript. –

1

Trattare un oggetto jQuery come un array è un'applicazione di duck typing. From Wikipedia:

Nella programmazione di computer con linguaggi di programmazione orientata agli oggetti, anatra digitando è uno stile di tipizzazione dinamica in cui la corrente set di un oggetto di metodi e proprietà determina la semantica vigenti, piuttosto della sua eredità da un particolare classe o implementazione di un'interfaccia specifica .

In altre parole, non è importante che la funzione jQuery effettivamente restituire un'istanza array, purché fornisce le proprietà necessarie (esempiolength, indici numerici) e metodi per agire come un array.

JavaScript ha altri oggetti simili a. Ad esempio, l'oggetto arguments non è un array, ma ha proprietà (come length) che consentono di fingere che sia.

0

Non sono sicuro di quale sia questa follia simile ad "array" dalle altre risposte. Non esiste una terminologia standard per "array-like".

La differenza effettiva qui è la differenza tra una matrice effettiva, che è una raccolta di elementi rispetto a una lista collegata che è una raccolta di riferimenti. In riferimento al DOM, un elenco collegato viene correttamente chiamato elenco di nodi.Questi articlea avere più informazioni:

http://www.mindcracker.com/Story/1016/interview-question-difference-between-linked-list-and-array.aspx

http://www.sitepoint.com/a-collection-is-not-an-array/

http://blog.duruk.net/2011/06/19/nodelists-and-arrays-in-javascript/

Problemi correlati