2009-09-27 15 views
14

Obiekty jQuery działają jak tablice bez zanieczyszczania macierzystych prototypów. Jak to osiągnąć?W jaki sposób obiekty jQuery naśladują tablice?

Wiem, że to nie tylko obiekty z kluczami numerycznymi - więc może to tylko kwestia zapewnienia odpowiednich metod (coś w stylu: jQuery.prototype.indexOf = Array.prototype.indexOf).

Mam google i patrzę na źródło, ale nie mogę znaleźć ostatecznej odpowiedzi.

+3

Co sprawia, że ​​uważasz, że to nie tylko obiekty z kluczami numerycznymi? – Marius

+2

Po pierwsze, Firebug wyświetla obiekty jQuery jako tablice, ale nie takie ręcznie tworzone obiekty - i wątpię, czy ma ono specjalną obsługę dla jQuery. – AnC

Odpowiedz

26

Mimo że obiekty jQuery działają jak tablice, są one w rzeczywistości tylko obiektami podobnymi do tablic . Obiektem podobnym do tablicy jest obiekt, który używa kluczy numerycznych i ma właściwość length - to jest minimum potrzebne do kompatybilności z native array methods.

Ponieważ obiekty jQuery są tylko obiektami tablicowymi i nie są rzeczywistymi obiektami macierzystymi (np. indexOf lub reverse), nie można wywoływać bezpośrednio. Możesz jednak użyć Array.prototype lub rozszerzyć funkcjonalność jQuery.

$('div').reverse(); // TypeError: $("div").reverse is not a function 

// we can use Array.prototype though 
Array.prototype.reverse.apply($('div')); 

// or we can extend jQuery very easily 
$.fn.reverse = Array.prototype.reverse; 
$('div').reverse(); // now it works! 

Masz rację, zakładając, że Firebug nie zawiera specjalnych obudów do formatowania obiektów jQuery. Szybkie wyszukiwanie ujawnia a relevant post na liście mailingowej Firebug. Zakładając, że informacje są nadal poprawne (post jest od stycznia) Firebug sformatuje obiekt jako tablicę, jeśli ma on skończoną długość skończoną długość i metodę.

JQuery spełnia oba te kryteria, ale their implementation of splice to nic innego jak bezpośrednia kopia natywnej metody Array. Jest to nieudokumentowane, co oznacza, że ​​jest albo tylko do użytku wewnętrznego, albo może dodane tylko w celu nakłonienia Firebug do ładnego formatowania obiektów jQuery.

+0

To jest doskonałe - dzięki! Wahałbym się dodać metodę łączenia tylko po to, aby wyglądała ładnie w Firebug, ale to tylko drobny szczegół. (PS: W twoim poście jest literówka, wspominasz o "plasterku" zamiast "splice".) – AnC

+0

Dziękuję - poprawiono. Sugeruję tylko, że metoda 'splice' została dodana do jQuery specjalnie dla Firebuga, ponieważ gałąź jQuery's 1.2 _nie_ nie ujawnia takiej metody. Rzeczywiście, pamiętam krótki okres, w którym moje obiekty jQuery nie były sformatowane jako 'Arrays' w Firebug. Oczywiście wprowadzenie metody w wersji 1.3 może mieć właśnie zbieg okoliczności. –

+1

Dziękuję - to było interesujące przypadek. Zauważam, że inspektor sieci Safari wydaje się używać tych samych kryteriów - "długość" obiektu i "splice" - do formatowania obiektów jako tablic: 'var o; o = {length: 2, splice: function (x) {}}; '=>' [] '(tho 'firebug rygorystycznie drukuje:' [undefined, undefined] '). –

5

Look w kodzie jquery (rozwój), linia 139:

// Force the current matched set of elements to become 
// the specified array of elements (destroying the stack in the process) 
// You should use pushStack() in order to do this, but maintain the stack 
setArray: function(elems) { 
    // Resetting the length to 0, then using the native Array push 
    // is a super-fast way to populate an object with array-like properties 
    this.length = 0; 
    Array.prototype.push.apply(this, elems); 
     return this; 
}, 

To dlatego, że każdy wynik zapytań jQuery jest tablicą.

+0

Dzięki. Widziałem to również, ale to nie wydaje się wystarczające: var MyObj = funkcja (args) { this.length = 0; Array.prototype.push.apply (to, argumenty); zwróć to; }; var obj = new MyObj ("cześć", "świat"); – AnC

+1

Nie zwracaj "tego" z konstruktora! Również 'var' ustawia zmienną, ale nie zwraca wartości; jeśli uruchamiasz ten fragment w narzędziu podobnym do Firebug: 'var MyObj = function (args) {this.length = 0; Array.prototype.push.apply (to, argumenty); }; obj = new MyObj ("cześć", "świat"); ' –

+0

Jestem zdezorientowany: Jeśli to nie jest konstruktor," ten "nie będzie obiektem (tylko okno) !? Czy możesz podać roboczą próbkę? – AnC

Powiązane problemy