Як я можу виявити, якщо селектор повертає нуль?


271

Який найкращий спосіб виявити, якщо jQuery-селектор повертає порожній об’єкт. Якщо ти зробиш:

alert($('#notAnElement'));

ви отримуєте [object Object], так що я це роблю зараз:

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

який буде писати "невизначений", і ви можете зробити перевірку на це. Але це здається дуже поганим. Який ще спосіб?

Відповіді:


494

Мій улюблений - розширити jQuery за допомогою цієї крихітної зручності:

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

Використовується як:

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

Більш чітке, ніж використання довжини.


2
Чому ви загорнули "це" всередині $ ()? чи не «це» в цьому контексті насправді вказувало б на об’єкт jQuery?
Адам Атта

1
Я вважаю, що повернення thisнабагато корисніше, ніж true. Дивіться мою відповідь щодо перенесення presenceметоду Rails .
Марк-Андре Лафортун

5
Якщо ви хочете зберегти здатність до ланцюжка, якщо функція повертається в істину, або якщо ви хочете використовувати цей метод для присвоєння thisзмінній, я рекомендую змінити оператор повернення на те, що має CSharp .
Ганна

1
Маґнар, чи можете ви пояснити, як насправді працює ця функція "розширення"? Я припускаю, що це концепція Javascript, а не суворо JQuery. Я розглядав прототипування, але не впевнений, чи це стосується тут і чому синтаксис буде "$ .fn."
KyleM

3
@Адам Так. Але в цьому випадку вам слід просто скинути існуючу перевірку, враховуючи, як працює jQuery. Він просто нічого не зробить, якщо немає елемента, що відповідає селектору.
Магнар


67

Селектор повертає масив об’єктів jQuery. Якщо не знайдено відповідних елементів, він повертає порожній масив. Ви можете перевірити .lengthколекцію, повернуту селектором, або перевірити, чи не визначено перший елемент масиву.

Ви можете використовувати будь-які наведені нижче приклади всередині оператора IF, і всі вони дають однаковий результат. Щоправда, якщо селектор знайшов відповідний елемент, помилково інакше.

$('#notAnElement').length > 0
$('#notAnElement').get(0) !== undefined
$('#notAnElement')[0] !== undefined

1
Я використовую, .lengthякщо код не гарячий. Це, звичайно, найбільш зрозуміло з наміром. Також .size()застаріла і є роками (з 1,8 року). Я просто збираюсь відредагувати вашу відповідь і видалити її, сміливо додайте її назад із приміткою, але вона така стара, я думаю, що краще пішло.
Еван Керролл

1
Технічно він повертає об’єкт jQuery, який не містить вузлів DOM. Скажімо, що повертає порожній масив, це неправильно.
Ярмарок

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/


6
@Ehsan Насправді це не дублікат прийнятої відповіді ... зауважте, що прийнята відповідь повертає лише істину / хибність, тоді як ця відповідь повертає або вихідний об'єкт ("цей"), або хибний. Ця відповідь дозволяє робити додаткові речі із поверненим значенням (наприклад, додаткове ланцюжкове функціонування), якщо воно не хибне.
RSW

1
У мого стандартного набору інструментів я точно такий же код. Ця форма еквівалентна object.presence в Rails і надзвичайно корисна в перехідній конструкції, яку @CSharp описує.
inopinatus

Це хороша відповідь, але було б корисно, якщо ви поясните, що відбувається, якщо НІКОЛЬ з перевірених елементів не існує. Коротка відповідь: TypeError: firstExistingElement.doSomething is not a function. Ви можете обернути всю присвоєння / тест змінної у if () і зробити щось лише якщо елемент знайдений ....
Stephen R

9

Мені подобається використовувати presence, натхненну Ruby on Rails :

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

Ваш приклад стає:

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

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

$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"


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/

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.