¿Cómo puedo detectar si un selector devuelve nulo?

271

¿Cuál es la mejor manera de detectar si un jQuery-selector devuelve un objeto vacío? Si lo haces:

alert($('#notAnElement'));

obtienes [Object Object], así que la forma en que lo hago ahora es:

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

que escribirá "indefinido", por lo que puede hacer una comprobación para eso. Pero parece muy malo. ¿Qué otra forma hay?

peirix
fuente

Respuestas:

494

Mi favorito es extender jQuery con esta pequeña comodidad:

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

Usado como:

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

Más explícito que usar longitud.

Magnar
fuente
2
¿Por qué envolviste 'esto' dentro de un $ ()? ¿no 'esto' en este contexto realmente apuntaría al objeto jQuery?
Adham Atta
1
Encuentro que regresar thises mucho más útil que true. Vea mi respuesta portando el presencemétodo de Rails .
Marc-André Lafortune
55
Si desea mantener la capacidad de encadenar, si la función devuelve verdadero, o si desea utilizar este método para asignar thisa una variable, recomendaría cambiar la declaración de retorno a lo que CSharp tiene.
Hanna
1
Magnar, ¿puedes explicar cómo funciona realmente esta función de "extensión"? Supongo que es un concepto de Javascript y no estrictamente un concepto de JQuery. Investigué la creación de prototipos, pero no estoy seguro de si eso se aplica aquí y por qué la sintaxis sería "$ .fn".
KyleM
3
@ Adam Sí. Pero en ese caso, solo debe soltar el control de existencia, dado cómo funciona jQuery. Simplemente no hará algo si no hay ningún elemento que coincida con el selector.
Magnar
197
if ( $("#anid").length ) {
  alert("element(s) found")
} 
else {
  alert("nothing found")
}
duckyflip
fuente
67

El selector devuelve una matriz de objetos jQuery. Si no se encuentran elementos coincidentes, devuelve una matriz vacía. Puede verificar la .lengthcolección devuelta por el selector o verificar si el primer elemento de la matriz está 'indefinido'.

Puede usar cualquiera de los siguientes ejemplos dentro de una instrucción IF y todos producen el mismo resultado. Es cierto que si el selector encuentra un elemento coincidente, falso en caso contrario.

$('#notAnElement').length > 0
$('#notAnElement').get(0) !== undefined
$('#notAnElement')[0] !== undefined
Jose basilio
fuente
1
Lo uso a .lengthmenos que el código esté caliente. Ciertamente es el más claro con intención. Además, .size()está en desuso y lo ha estado durante años (desde 1.8). Solo voy a editar su respuesta y eliminarla, siéntase libre de agregarla nuevamente con una nota, pero es tan antigua que creo que es mejor que se haya ido.
Evan Carroll
1
Técnicamente, devuelve un objeto jQuery que no contiene nodos DOM. Decir que devuelve una matriz vacía no está bien.
Vigrant
39

Me gusta hacer algo como esto:

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

Entonces puedes hacer algo como esto:

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
fuente
66
@Ehsan En realidad no es un duplicado de la respuesta aceptada ... tenga en cuenta que la respuesta aceptada solo devuelve verdadero / falso mientras que esta respuesta devuelve el objeto original ("esto") o falso. Esta respuesta le permite hacer cosas adicionales con el valor de retorno (como el encadenamiento de funciones adicionales) si no es falso.
RSW
1
Tengo exactamente el mismo código en mi kit de herramientas estándar. Esta forma es equivalente a object.presence en Rails y súper útil en la construcción fallida que describe @CSharp.
inopinatus
Esta es una buena respuesta, pero sería útil si explica qué sucede si NINGUNO de los elementos probados existe. Respuesta corta: TypeError: firstExistingElement.doSomething is not a function. Puede ajustar toda la asignación / prueba de variables en un if () y solo hacer algo si se encuentra un elemento ...
Stephen R
9

Me gusta usar presence, inspirado en Ruby on Rails :

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

Tu ejemplo se convierte en:

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

Me parece superior a la propuesta $.fn.existsporque todavía puede usar operadores booleanos o if, pero el resultado verdadero es más útil. Otro ejemplo:

$ul = $elem.find('ul').presence() || $('<ul class="foo">').appendTo($elem)
$ul.append('...')
Marc-André Lafortune
fuente
7

Mi preferencia, y no tengo idea de por qué esto no está ya en jQuery:

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

Usado así:

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

O, como se ve en CoffeeScript:

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

Es posible que desee hacer esto todo el tiempo de forma predeterminada. He estado luchando por ajustar la función jquery o el método jquery.fn.init para hacer esto sin error, pero puede hacer un cambio simple en la fuente jquery para hacer esto. Se incluyen algunas líneas circundantes que puede buscar. Recomiendo buscar fuente jquery paraThe 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 = {

Por último, pero no menos importante, puede obtener el código fuente de jquery sin comprimir aquí: http://code.jquery.com/

Devin G. Rhode
fuente