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')


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.


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! ');
}

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


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


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);

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


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"];
}

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


-9
var elArray = [];
var elObjeto = {};

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

elObjeto.constructor == Array//FALSE
elObjeto.constructor == Object//TRUE

11
Zrzuty kodu bez wyjaśnienia rzadko są przydatne. Rozważ dodanie kontekstu do swojej odpowiedzi.
Chris
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.