Sprawdź, czy obiekt jest obiektem jQuery

601

Czy istnieje szybki sposób sprawdzenia, czy obiekt jest obiektem jQuery czy rodzimym obiektem JavaScript?

przykład:

var o = {};
var e = $('#element');

function doStuff(o) {
    if (o.selector) {
        console.log('object is jQuery');
    }
}

doStuff(o);
doStuff(e);

oczywiście powyższy kod działa, ale nie jest bezpieczny. Możesz potencjalnie dodać klawisz wyboru do oobiektu i uzyskać ten sam wynik. Czy istnieje lepszy sposób upewnienia się, że obiekt faktycznie jest obiektem jQuery?

Coś zgodnego z (typeof obj == 'jquery')

David Hellsing
źródło
3
Począwszy od jQuery 3.0, zdecydowanie nie jest to poprawny sposób sprawdzania, czy obiekt jest obiektem jQuery, ponieważ selectorwłaściwość została dawno przestarzała i usunięta w 3.0. Nawet we wcześniejszych wersjach obiekt jQuery może mieć pusty ciąg selektora, na przykład $(window)nie ma selektora. Użyj instanceofzamiast tego.
Dave Methvin

Odpowiedzi:

878

Możesz użyć instanceofoperatora:

if (obj instanceof jQuery){
    console.log('object is jQuery');
}

Objaśnienie : jQueryfunkcja (aka $) jest zaimplementowana jako funkcja konstruktora . Funkcje konstruktora należy wywoływać z newprefiksem.

Kiedy dzwonisz $(foo), wewnętrznie jQuery tłumaczy to na new jQuery(foo)1 . JavaScript przechodzi do inicjalizacjithis wewnątrz funkcji konstruktora, aby wskazać nowe wystąpienie jQuery, ustawiając jego właściwości na właściwości znalezione na jQuery.prototype(aka jQuery.fn). W ten sposób otrzymujesz newobiekt gdzie instanceof jQueryjest true.


1 To jest właściwienew jQuery.prototype.init(foo) : logika konstruktora została przeniesiona do innej wywoływanej funkcji konstruktora init, ale koncepcja jest taka sama.

Półksiężyc Świeży
źródło
8
Masz na myśli if (obj instanceof jQuery){...}?
Nigel Angel,
2
@NigelAngel: Tak, o to mu chodzi :)
ChaseMoskal
12
Nie działa to w przypadku wielu instancji jQuery na stronie.
Georgii Ivankin
5
@CrescentFresh Mam na myśli, jeśli mam $ w mojej bieżącej przestrzeni nazw wskazującej na jQuery2 i mam obiekt z zewnętrznej przestrzeni nazw (gdzie $ to jQuery1) niż nie mam możliwości użycia instanceof do sprawdzenia, czy ten obiekt jest obiektem jQuery.
Georgii Ivankin
6
Jeśli nie jesteś pewien, czy jQuery jest ładowany w czasie if, można wydłużyć sprawdź, typeof jQuery === 'function' && obj instanceof jQueryponieważ jQuerynie muszą być zadeklarowane w porządku dla typeofoperatora do pracy bez rzuca błąd.
Patrick Roberts,
105

Możesz także użyć właściwości .jquery, jak opisano tutaj: http://api.jquery.com/jquery-2/

var a = { what: "A regular JS object" },
b = $('body');

if ( a.jquery ) { // falsy, since it's undefined
    alert(' a is a jQuery object! ');    
}

if ( b.jquery ) { // truthy, since it's a string
    alert(' b is a jQuery object! ');
}
mt81
źródło
12
Jak zauważył David w pytaniu, sprawdzanie właściwości zmiennej, której wartość może być zerowa (tj. Jeśli „a” lub „b” są zerowe), nie jest bezpieczne (spowoduje wygenerowanie błędu TypeError). Użycie „b instanceof jQuery” jest lepsze.
rstackhouse
23
Ten sposób działa, jeśli jQuery nie jest załadowany, natomiast b instanceof jQueryzgłasza błąd ReferenceError, jeśli jQuery nie jest dostępny na stronie. Oba podejścia są przydatne w różnych przypadkach.
Nate
Być może bardziej wydajny, ale nadal nie jest bezpieczny. Może to wymagać try ... catch, szczególnie w oldIE.
ClarkeyBoy
W przypadkach, w których możliwe jest, że jQuery nie jest załadowany, możesz użyćif ((typeof jQuery !== 'undefined') && (obj instanceof jQuery)) {...
Harry Pehkonen
To nie jest tak dobry przykład .. bardziej prawdopodobne, aże byłby to węzeł DOM, document.bodya wtedy teoretycznie istnieje szansa, że jqueryklucz jakoś pojawił się na łańcuchu tego węzła.
vsync
30

Sprawdź operator instanceof .

var isJqueryObject = obj instanceof jQuery
Corey Sunwold
źródło
26

Najlepszym sposobem sprawdzenia wystąpienia obiektu jest operator instanceof lub metoda to ProtrotOf (), która sprawdza, czy prototyp obiektu znajduje się w łańcuchu prototypów innego obiektu.

obj instanceof jQuery;
jQuery.prototype.isPrototypeOf(obj);

Ale czasami może się nie powieść w przypadku wielu instancji jQuery w dokumencie. Jak wspomniał @Georgiy Ivankin:

jeśli $w mojej bieżącej przestrzeni nazw wskazuję jQuery2i mam obiekt z zewnętrznej przestrzeni nazw (gdzie $jest jQuery1), to nie mam sposobu, aby instanceofsprawdzić, czy ten obiekt jest jQueryobiektem

Jednym ze sposobów rozwiązania tego problemu jest aliasing obiektu jQuery w zamknięciu lub IIFE

//aliases jQuery as $
(function($, undefined) {
    /*... your code */

    console.log(obj instanceof $);
    console.log($.prototype.isPrototypeOf(obj));

    /*... your code */
}(jQuery1));
//imports jQuery1

Innym sposobem rozwiązania tego problemu jest zapytanie o jquerynieruchomość wobj

'jquery' in obj

Jeśli jednak spróbujesz przeprowadzić sprawdzanie z wartościami pierwotnymi, wygeneruje błąd, więc możesz zmodyfikować poprzednie sprawdzenie, upewniając objsię, żeObject

'jquery' in Object(obj)

Chociaż poprzedni sposób nie jest najbezpieczniejszy (możesz utworzyć 'jquery'właściwość w obiekcie), możemy poprawić sprawdzanie poprawności, pracując z obiema metodami:

if (obj instanceof jQuery || 'jquery' in Object(obj)) { }

Problem polega na tym, że każdy obiekt może zdefiniować właściwość jqueryjako własną, dlatego lepszym rozwiązaniem byłoby zapytanie w prototypie i upewnienie się, że obiekt nie jest nulllubundefined

if (obj && (obj instanceof jQuery || obj.constructor.prototype.jquery)) { }

Ze względu na przymus The ifstwierdzenie uczyni zwarcie poprzez ocenę &&operatora kiedy objto każdy z falsy wartości ( null, undefined, false, 0,"" ), a następnie przechodzi do wykonywania innych walidacji.

Wreszcie możemy napisać funkcję narzędzia:

function isjQuery(obj) {
  return (obj && (obj instanceof jQuery || obj.constructor.prototype.jquery));
}

Spójrzmy na: Operatory logiczne i prawda / fałsz

jherax
źródło
Jak to jednak poprawia bezpieczeństwo? Obiekty inne niż jQuery z właściwością jquery nadal byłyby źle wykrywane. Nie widzę też, co jeszcze może się przydać przy obu tych podejściach.
Gui Prá
jest to prosty sposób na sprawdzenie, czy obiekt jest obiektem jQuery, jeśli z jakiegokolwiek powodu podejrzewasz, że ktoś tworzy obiekty o właściwościach takich jak jquery , możesz utworzyć bardziej solidny weryfikator, tj. sprawdzanie właściwości w prototypie: myObj .constructor.prototype.jquery lub jeszcze lepiej, możesz użyć funkcji Object.prototype.isPrototypeOf ()
jherax
1
Jeśli ||którykolwiek z 'jquery' in Object(obj)nich ma opcję, spowoduje to wyczerpanie, ponieważ nie zapobiegnie przejściu weryfikacji przez obiekty inne niż jQuery z tą właściwością. Uważam jednak, że sprawdzenie tej właściwości w prototypie poprawia sytuację. Może powinieneś dodać to do swojej odpowiedzi! Nie wydaje mi się, żeby inna odpowiedź tutaj wspominała o takiej możliwości :)
Gui Prá
1
nie wystarczy obj.__proto__.jqueryzamiast obj.constructor.prototype.jquery? tylko trochę krótko :)
Axel
1
@Axel tak, to też działa :). Użyłem, constructor.prototypeponieważ objma to być instancja konstruktora jQuery. Z drugiej strony __proto__jest dostępny dla każdego rodzaju obiektu.
jherax
3
return el instanceof jQuery ? el.size() > 0 : (el && el.tagName);
johnchou
źródło
Aby sprawdzić element DOM, lepiej użyć nodeTypewłaściwości i upewnić się, że booleanwartość zostanie zwrócona, możesz użyć podwójnej negacji!!(el && el.nodeType)
jherax
3

Istnieje jednak jeszcze jeden sposób sprawdzenia obiektu w jQuery.

jQuery.type(a); //this returns type of variable.

Dałem przykład, aby zrozumieć rzeczy, link jsfiddle

Shaunak Shukla
źródło
2

Dla tych, którzy chcą wiedzieć, czy obiekt jest obiektem jQuery bez zainstalowanego jQuery, następujący fragment kodu powinien wykonać tę pracę:

function isJQuery(obj) {
  // Each jquery object has a "jquery" attribute that contains the version of the lib.
  return typeof obj === "object" && obj && obj["jquery"];
}
Karl.S
źródło
1

Możesz sprawdzić, czy obiekt jest generowany przez JQuery za pomocą jquerywłaściwości:

myObject.jquery // 3.3.1

=> zwraca numer wersji JQuery, jeśli obiekt utworzony przez JQuery. => w przeciwnym razie zwracaundefined

Jérôme-Victor Toulouse
źródło
-9
var elArray = [];
var elObjeto = {};

elArray.constructor == Array //TRUE
elArray.constructor == Object//TALSE

elObjeto.constructor == Array//FALSE
elObjeto.constructor == Object//TRUE
Gabriel Seg
źródło
11
Zrzuty kodu bez wyjaśnienia rzadko są przydatne. Rozważ dodanie kontekstu do swojej odpowiedzi.
Chris