Как я могу определить, возвращает ли селектор ноль?

271

Как лучше всего определить, возвращает ли jQuery-селектор пустой объект? Если вы делаете:

alert($('#notAnElement'));

вы получаете [объект объекта], поэтому способ, которым я делаю это сейчас:

alert($('#notAnElement').get(0));

который напишет "undefined", и поэтому вы можете проверить это. Но это выглядит очень плохо. Какой еще путь есть?

peirix
источник

Ответы:

494

Мой фаворит - расширить jQuery с помощью этого небольшого удобства:

$.fn.exists = function () {
    return this.length !== 0;
}

Используется как:

$("#notAnElement").exists();

Более явный, чем использование длины.

Magnar
источник
2
Почему вы обернули это в $ ()? не будет ли 'this' в этом контексте фактически указывать на объект jQuery?
Адхам Атта
1
Я считаю, что возвращение thisгораздо полезнее, чем true. Смотрите мой ответ, портирующий presenceметод Rails .
Марк-Андре Лафортун
5
Если вы хотите сохранить возможность цепочки, если функция вернет true, или если вы хотите использовать этот метод для присваивания thisпеременной, я бы рекомендовал изменить инструкцию return на то, что имеет CSharp .
Ханна
1
Magnar, не могли бы вы объяснить, как на самом деле работает эта функция «расширения»? Я предполагаю, что это концепция Javascript, а не концепция JQuery. Я посмотрел на прототипирование, но я не уверен, применимо ли это здесь и почему синтаксис будет "$ .fn".
KyleM
3
@ Адам Да. Но в этом случае вам нужно просто снять проверку с учетом того, как работает jQuery. Это просто не будет делать что-то, если нет элемента, соответствующего селектору.
Магнар
197
if ( $("#anid").length ) {
  alert("element(s) found")
} 
else {
  alert("nothing found")
}
duckyflip
источник
67

Селектор возвращает массив объектов jQuery. Если подходящих элементов не найдено, возвращается пустой массив. Вы можете проверить .lengthколлекцию, возвращаемую селектором, или проверить, является ли первый элемент массива неопределенным.

Вы можете использовать любые следующие примеры внутри оператора IF, и все они дают одинаковый результат. True, если селектор нашел соответствующий элемент, иначе false.

$('#notAnElement').length > 0
$('#notAnElement').get(0) !== undefined
$('#notAnElement')[0] !== undefined
Хосе Базилио
источник
1
Я использую, .lengthесли код не горячий. Это, безусловно, наиболее ясно с намерением. Кроме того, .size()является устаревшим и был в течение многих лет (с 1,8). Я просто собираюсь отредактировать ваш ответ и удалить его, не стесняйтесь добавлять его обратно с примечанием, но оно настолько старое, что, думаю, его уже нет.
Эван Кэрролл
1
Технически он возвращает объект jQuery, который не содержит узлов DOM. Сказать, что он возвращает пустой массив, неправильно.
Vigrant
39

Мне нравится делать что-то вроде этого:

$.fn.exists = function(){
    return this.length > 0 ? this : false;
}

Итак, вы можете сделать что-то вроде этого:

var firstExistingElement = 
    $('#iDontExist').exists() ||      //<-returns false;
    $('#iExist').exists() ||          //<-gets assigned to the variable 
    $('#iExistAsWell').exists();      //<-never runs

firstExistingElement.doSomething();   //<-executes on #iExist

http://jsfiddle.net/vhbSG/

CSharp
источник
6
@Ehsan На самом деле это не дубликат принятого ответа ... обратите внимание, что принятый ответ возвращает только true / false, в то время как этот ответ возвращает либо исходный объект ("this"), либо false. Этот ответ позволяет вам выполнять дополнительные действия с возвращаемым значением (например, добавление цепочки дополнительных функций), если оно не ложно.
RSW
1
У меня точно такой же код в моем стандартном наборе инструментов. Эта форма эквивалентна object.presence в Rails и очень полезна в сквозной конструкции, описанной @CSharp.
inopinatus
Это хороший ответ, но было бы полезно, если бы вы объяснили, что происходит, если НИКАКОГО из протестированных элементов не существует. Короткий ответ: TypeError: firstExistingElement.doSomething is not a function. Вы можете обернуть всю переменную присваивания / теста в if () и делать что-то только в том случае, если элемент найден ....
Стивен R
9

Мне нравится использовать presence, вдохновленный Ruby on Rails :

$.fn.presence = function () {
    return this.length !== 0 && this;
}

Ваш пример становится:

alert($('#notAnElement').presence() || "No object found");

Я считаю, что это лучше предложенного, $.fn.existsпотому что вы все еще можете использовать логические операторы или if, но правдивый результат более полезен. Другой пример:

$ul = $elem.find('ul').presence() || $('<ul class="foo">').appendTo($elem)
$ul.append('...')
Марк-Андре Лафортун
источник
7

Мои предпочтения, и я понятия не имею, почему это не в jQuery:

$.fn.orElse = function(elseFunction) {
  if (!this.length) {
    elseFunction();
  }
};

Используется так:

$('#notAnElement').each(function () {
  alert("Wrong, it is an element")
}).orElse(function() {
  alert("Yup, it's not an element")
});

Или, как это выглядит в CoffeeScript:

$('#notAnElement').each ->
  alert "Wrong, it is an element"; return
.orElse ->
  alert "Yup, it's not an element"
nilskp
источник
0

Вы можете делать это все время по умолчанию. Я изо всех сил пытался обернуть функцию jquery или метод jquery.fn.init, чтобы сделать это без ошибок, но вы можете сделать простое изменение в источнике jquery, чтобы сделать это. Включены некоторые окружающие линии, которые вы можете искать. Я рекомендую поискать источник jquery дляThe jQuery object is actually just the init constructor 'enhanced'

var
  version = "3.3.1",

  // Define a local copy of jQuery
  jQuery = function( selector, context ) {

    // The jQuery object is actually just the init constructor 'enhanced'
    // Need init if jQuery is called (just allow error to be thrown if not included)
    var result = new jQuery.fn.init( selector, context );
    if ( result.length === 0 ) {
      if (window.console && console.warn && context !== 'failsafe') {
        if (selector != null) {
          console.warn(
            new Error('$(\''+selector+'\') selected nothing. Do $(sel, "failsafe") to silence warning. Context:'+context)
          );
        }
      }
    }
    return result;
  },

  // Support: Android <=4.0 only
  // Make sure we trim BOM and NBSP
  rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;

jQuery.fn = jQuery.prototype = {

И последнее, но не менее важное: вы можете получить несжатый исходный код jquery здесь: http://code.jquery.com/

Девин Дж Род
источник