Перевірте, чи об'єкт є об'єктом jQuery


601

Чи існує швидкий спосіб перевірити, чи об’єкт є об'єктом 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функція (ака $) реалізована як конструкторська функція . Функції конструктора слід викликати з newпрефіксом.

Коли ви телефонуєте $(foo), jQuery внутрішньо переводить це на new jQuery(foo)1 . JavaScript переходить до ініціалізації thisвсередині функції конструктора, щоб вказати на новий екземпляр jQuery, встановивши його властивості тим, які знайдені у jQuery.prototype(ака 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 під час оператора if, ви можете продовжити перевірку, 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 недоступний на сторінці. Обидва підходи корисні в різних випадках.
Нейт

Можливо, ефективніше, але все ж не безпечно. Це може знадобитися 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 документа. Як згадував @Georgiy Ivankin:

якщо я маю $в моєму поточному просторі імен вказівку 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));
}

Давайте подивимось на: Логічні оператори та truthy / фальшивість


Як це покращує безпеку? Об'єкти, що не містять jQuery із властивістю jquery, все одно будуть виявлені неправильно. Я не бачу, що ще може використовувати «покращення», використовуючи обидва підходи.
Gui Prá

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

1
Якщо у вас є що- ||небудь із знаком a 'jquery' in Object(obj), воно переходить у стік, оскільки це не заважатиме об'єктам, які не містять jQuery з цим властивістю, пройти перевірку. Я вважаю, що перевірка цього властивості в прототипі покращує ситуацію. Можливо, ви повинні додати це до своєї відповіді! Я не думаю, що жодна інша відповідь тут згадує таку можливість :)
Gui Prá

1
це obj.__proto__.jqueryзамість obj.constructor.prototype.jqueryнедостатньо? трохи трохи :)
Аксель

1
@Axel так, це теж працює :). Я використовував, constructor.prototypeтому що objповинен бути екземпляром конструктора, тобто jQuery. З іншого боку __proto__, доступний для будь-якого виду об’єктів.
jherax

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.