Jak mogę wykryć, czy selektor zwraca wartość null?


271

Jaki jest najlepszy sposób na wykrycie, czy selektor jQuery zwraca pusty obiekt. Jeśli zrobisz:

alert($('#notAnElement'));

dostajesz [Object Object], więc teraz to robię:

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

który napisze „niezdefiniowany”, a więc możesz to sprawdzić. Ale wydaje się bardzo źle. Jaki jest inny sposób?

Odpowiedzi:


494

Moim ulubionym jest rozszerzenie jQuery z tą niewielką wygodą:

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

Używany jak:

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

Bardziej wyraźne niż używanie długości.


2
Dlaczego „zawinąłeś” to w $ ()? czy „to” w tym kontekście nie wskazuje na obiekt jQuery?
Adham Atta

1
Uważam, że powrót thisjest o wiele bardziej pomocny niż true. Zobacz moją odpowiedź przenoszącą presencemetodę Railsów .
Marc-André Lafortune

5
Jeśli chcesz zachować możliwość tworzenia łańcucha, jeśli funkcja zwróci true, lub jeśli chcesz użyć tej metody do przypisania thisdo zmiennej, zaleciłbym zmianę instrukcji return na to, co ma CSharp .
Hanna,

1
Magnar, czy możesz wyjaśnić, jak działa ta funkcja „rozszerzenia”? Zakładam, że jest to koncepcja Javascript, a nie koncepcja JQuery. Zajrzałem do prototypowania, ale nie jestem pewien, czy dotyczy to tutaj i dlaczego składnia miałaby postać „$ .fn”.
KyleM

3
@Adam Tak. Ale w takim przypadku powinieneś po prostu usunąć sprawdzanie istnienia, biorąc pod uwagę, jak działa jQuery. Po prostu nic nie zrobi, jeśli żaden element nie pasuje do selektora.
Magnar,

197
if ( $("#anid").length ) {
  alert("element(s) found")
} 
else {
  alert("nothing found")
}

67

Selektor zwraca tablicę obiektów jQuery. Jeśli nie znaleziono pasujących elementów, zwraca pustą tablicę. Możesz sprawdzić .lengthkolekcję zwróconą przez selektor lub sprawdzić, czy pierwszy element tablicy jest „niezdefiniowany”.

Możesz użyć dowolnego z poniższych przykładów w instrukcji JEŻELI i wszystkie dają ten sam wynik. Prawda, jeśli selektor znalazł pasujący element, w przeciwnym razie fałsz.

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

1
Używam, .lengthchyba że kod jest gorący. Jest to z pewnością najbardziej jasne z intencją. Jest również .size()przestarzałe i jest od lat (od 1.8). Po prostu edytuję twoją odpowiedź i ją usunę, dodaj ją z powrotem z notatką, ale jest tak stara, myślę, że lepiej jej nie ma.
Evan Carroll

1
Technicznie zwraca obiekt jQuery, który nie zawiera węzłów DOM. Powiedzenie, że zwraca pustą tablicę, jest niewłaściwe.
Vigrant

39

Lubię robić coś takiego:

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

Więc możesz zrobić coś takiego:

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 W rzeczywistości nie jest to duplikat zaakceptowanej odpowiedzi ... zauważ, że zaakceptowana odpowiedź zwraca tylko prawda / fałsz, podczas gdy ta odpowiedź zwraca oryginalny obiekt („to”) lub fałsz. Ta odpowiedź umożliwia wykonanie dodatkowych czynności z wartością zwracaną (na przykład tworzenie łańcuchów funkcji dodatkowych), jeśli nie jest to fałsz.
RSW

1
Mam dokładnie ten sam kod w moim standardowym zestawie narzędzi. Ta forma jest odpowiednikiem object.presence w Railsach i bardzo przydatna w przełomowej konstrukcji opisanej przez @CSharp.
inopinatus

To dobra odpowiedź, ale pomocne byłoby wyjaśnienie, co się stanie, jeśli ŻADNY z testowanych elementów nie istnieje. Krótka odpowiedź: TypeError: firstExistingElement.doSomething is not a function. Możesz owinąć całe przypisanie / test zmiennej w if () i zrobić coś tylko, jeśli element zostanie znaleziony ....
Stephen R

9

Lubię używać presence, zainspirowany Ruby on Rails :

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

Twój przykład to:

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

Uważam, że jest lepszy od proponowanego, $.fn.existsponieważ nadal można używać operatorów logicznych lub if, ale prawdziwy wynik jest bardziej użyteczny. Inny przykład:

$ul = $elem.find('ul').presence() || $('<ul class="foo">').appendTo($elem)
$ul.append('...')

7

Moje preferencje i nie mam pojęcia, dlaczego nie ma tego w jQuery:

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

Używany w ten sposób:

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

Lub, jak to wygląda w CoffeeScript:

$('#notAnElement').each ->
  alert "Wrong, it is an element"; return
.orElse ->
  alert "Yup, it's not an element"


0

Domyślnie możesz to robić cały czas. Próbowałem owinąć funkcję jquery lub metodę jquery.fn.init, aby zrobić to bez błędów, ale możesz to zrobić, wprowadzając prostą zmianę w źródle jquery. Uwzględniono niektóre otaczające linie, które można wyszukać. Polecam wyszukiwanie źródła jquery dlaThe 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 = {

Wreszcie nieskompresowany kod źródłowy jquery można uzyskać tutaj: http://code.jquery.com/

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.