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?

peirix
źródło

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.

Magnar
źródło
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")
}
duckyflip
źródło
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
Jose Basilio
źródło
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/

CSharp
źródło
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('...')
Marc-André Lafortune
źródło
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"
nilskp
źródło
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/

Devin G. Rhode
źródło