Проверьте, является ли объект объектом 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.