Проверьте, является ли объект объектом jQuery


602

Существует ли быстрый способ проверки, является ли объект объектом jQuery или собственным объектом JavaScript?

пример:

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

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

doStuff(o);
doStuff(e);

очевидно, приведенный выше код работает, но это не безопасно. Вы можете добавить селекторный ключ к oобъекту и получить тот же результат. Есть ли лучший способ убедиться, что объект на самом деле является объектом jQuery?

Что-то в соответствии с (typeof obj == 'jquery')


3
Начиная с jQuery 3.0, это определенно не правильный способ проверить, является ли объект объектом jQuery, потому что selectorсвойство давно устарело и удалено в 3.0. Даже в более ранних версиях объект jQuery может иметь пустую строку селектора, например, $(window)не имеет селектора. Используйте instanceofвместо этого.
Дейв Метвин

Ответы:


878

Вы можете использовать instanceofоператор:

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

Объяснение : jQueryфункция (aka $) реализована как функция-конструктор . Функции конструктора должны вызываться с newпрефиксом.

Когда вы звоните $(foo), внутренне jQuery переводит это в new jQuery(foo)1 . JavaScript приступает к инициализации thisвнутри функции конструктора, чтобы указать на новый экземпляр класса jQuery, установив его свойства в соответствии с теми, которые находятся в jQuery.prototype(aka jQuery.fn). Таким образом, вы получаете newобъект, где instanceof jQueryнаходится true.


1 Это на самом деле new jQuery.prototype.init(foo): логика конструктора была выгружена в другую вызываемую функцию конструктора init, но концепция та же самая.


8
Так ты имеешь в виду if (obj instanceof jQuery){...}?
Найджел Анхель

2
@NigelAngel: Да, это то, что он имеет в виду :)
ChaseMoskal

12
Это не работает в случае нескольких экземпляров jQuery на странице.
Георгий Иванкин

5
@CrescentFresh Я имею в виду, если у меня есть $ в моем текущем пространстве имен, указывающем на jQuery2, и у меня есть объект из внешнего пространства имен (где $ - это jQuery1), то у меня нет способа использовать instanceof для проверки, является ли этот объект объектом jQuery.
Георгий Иванкин

6
Если вы не уверены, загружен ли Jquery в момент , если заявление, вы можете продлить проверку быть , typeof jQuery === 'function' && obj instanceof jQueryтак как jQueryне должны быть объявлены в порядке для typeofоператора к работе , не бросать ошибку.
Патрик Робертс

105

Вы также можете использовать свойство .jquery, как описано здесь: 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
Как указывал в этом вопросе Дэвид , проверка свойства переменной, значение которой может быть равно нулю (т. Е. Если «a» или «b» были равны нулю), небезопасно (это вызовет ошибку TypeError). Лучше использовать "b instanceof jQuery".
rstackhouse

23
Этот способ работает, если jQuery не загружен, тогда как b instanceof jQueryвыдает ReferenceError, если jQuery не доступен на странице. Оба подхода полезны в разных случаях.
Nate

Возможно, более эффективно, но все же небезопасно. Это может потребоваться try ... catch, особенно в oldIE.
ClarkeyBoy

В случаях, когда возможно, что jQuery не загружен, вы можете использоватьif ((typeof jQuery !== 'undefined') && (obj instanceof jQuery)) {...
Гарри Пехконен

Это не очень хороший пример. Скорее всего, aэто будет узел DOM, document.bodyи тогда, теоретически, есть вероятность, что jqueryключ каким-то образом окажется поверх цепочки этого узла.
vsync


26

Лучший способ проверить экземпляр объекта - использовать оператор instanceof или метод isPrototypeOf (), который проверяет, находится ли прототип объекта в цепочке прототипов другого объекта.

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

Но иногда это может дать сбой в случае нескольких экземпляров jQuery в документе. Как отметил @ Георгий Иванкин:

если $в моем текущем пространстве имен указано, jQuery2и у меня есть объект из внешнего пространства имен (где $есть jQuery1), то у меня нет способа использовать instanceofдля проверки, является ли этот объект jQueryобъектом

Одним из способов решения этой проблемы является наложение псевдонима объекта jQuery в замыкании или IIFE.

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

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

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

Другой способ преодолеть эту проблему - запросить jqueryсвойство вobj

'jquery' in obj

Тем не менее, если вы попытаетесь выполнить эту проверку с примитивными значениями, он выдаст ошибку, так что вы можете изменить предыдущую проверку, обеспечивая , objчтобы бытьObject

'jquery' in Object(obj)

Хотя предыдущий способ не самый безопасный (вы можете создать 'jquery'свойство в объекте), мы можем улучшить проверку, работая с обоими подходами:

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

Проблема здесь состоит в том , что любой объект может определить свойство , jqueryкак самостоятельно, так лучше было бы спросить в прототипе, и убедитесь , что объект не является nullилиundefined

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

Из - за принуждения , то ifоператор будет сделать короткое замыкание путем оценки &&оператора , когда objлюбое из falsy значений ( null, undefined, false, 0,"" ), а затем переходит к выполнению других проверок.

Наконец, мы можем написать служебную функцию:

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

Давайте посмотрим на: логические операторы и правда / ложь


Как это повышает безопасность, хотя? Не-jQuery объекты со свойством jquery все равно будут ошибочно обнаружены. Я не вижу, что еще может улучшить "использование" обоих подходов.
Ги Пра

это простой способ проверить, является ли объект объектом jQuery, если по какой-либо причине вы подозреваете, что кто-то создает объекты со свойствами, такими как jquery , то вы можете создать более надежный валидатор, т.е. проверять свойства в прототипе: myObj .constructor.prototype.jquery или еще лучше, вы можете использовать функцию Object.prototype.isPrototypeOf ()
jherax

1
Однако если вы что- ||то из этого используете 'jquery' in Object(obj), то оно будет истощено, потому что это не помешает объектам, не являющимся jQuery, с этим свойством проходить проверку. Я верю, что проверка этого свойства в прототипе улучшает ситуацию. Может быть, вы должны добавить это в свой ответ! Я не думаю, что какой-либо другой ответ здесь упоминает
такую

1
не достаточно obj.__proto__.jqueryвместо obj.constructor.prototype.jquery? немного короче :)
Аксель

1
@ Аксель да, это тоже работает :). Я использовал, constructor.prototypeпотому что objпредполагается, что это экземпляр конструктора, то есть jQuery. С другой стороны __proto__доступен для любого вида объекта.
Джеракс

3
return el instanceof jQuery ? el.size() > 0 : (el && el.tagName);

Чтобы проверить элемент DOM, лучше использовать nodeTypeсвойство и обеспечить booleanвозвращаемое значение, вы можете использовать двойное отрицание!!(el && el.nodeType)
jherax


2

Для тех, кто хочет знать, является ли объект объектом jQuery без установленного jQuery, следующий фрагмент должен выполнить эту работу:

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

Вы можете проверить, создан ли объект JQuery, с помощью jqueryсвойства:

myObject.jquery // 3.3.1

=> вернуть номер версии JQuery, если объект создан JQuery. => в противном случае возвращаетсяundefined


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

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

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

11
Дампы кода без объяснения редко бывают полезными. Пожалуйста, рассмотрите возможность добавления некоторого контекста в ваш ответ.
Крис
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.