Eliminar elementos vacíos de un Array en Javascript

21 Dic 2010

Con la llegada de la nueva especificación ECMAScript 5, Javascript ha implementado de forma nativa una serie de métodos muy útiles para el manejo de sus objetos.

Uno de los más interesante es el depurado de los arrays mediante filter(), algo que hasta ahora precisaba de funciones específicas o del uso de nuestra librería favorita (jQuery, MooTools, etc). Su sintaxis es la siguiente:

array1.filter(callbackfn[, thisArg])

Este método devuelve los elementos de un array que cumplen la condición especificada en el callback o primer argumento.

Así, por ejemplo, podemos fácilmente eliminar aquellos elementos nulos o vacíos de un Array.

NOTA: Los elementos nulos o vacíos son aquellos que corresponden con los siguientes valores: false, null, undefined, 0, NaN.

var myArr = [ 'foo', 0, '', undefined, 'blue', null, 5, false, NaN];
myArrClean = myArr.filter(Boolean); // [foo, blue, 5]

¿Cómo funciona?

Como Boolean es, además de un constructor, una función, devuelve true o false según el valor de su argumento. De este modo, aquellos elementos del array vacíos o nulos, son evaluados como false y excluidos del resultado:

Boolean('foo') // true
Boolean(0) // false
Boolean(false) // false
Boolean(NaN) // false
Boolean({}) // true
Boolean('false') // true, ya que 'false' es un objeto String.

Otros métodos

Este método, como comentamos al principio, pertenece a la nueva especificación ECMA, por lo que no está presente en navegadores antiguos como Internet Explorer 8. Para ver una lista completa sobre los navegadores que los soportan, siempre podemos consultar la ECMAScript 5 compatibility table.

Si necesitamos esta función y nuestro navegador no ofrece el soporte, siempre podemos optar por crearla a mano:

Array.prototype.clean = function( deleteValue ) {
  for ( var i = 0, j = this.length ; i < j; i++ ) {
    if ( this[ i ] == deleteValue ) {
      this.splice( i, 1 );
      i--;
    }
  }
  return this;
};
 
test = new Array( "", "One", "Two", "", "Three", "", "Four" );
test.clean(""); // ["One", "Two", "Three", "Four"]

Hemos extendido el objeto nativo Array añadiéndole un nuevo método clean que actúa de una forma similar a filter():

array1.clean( elementToClean )

Mediante una comparación no-estricta, la función evalúa cada valor del array con la cadena enviada en el argumento (elementToClean) para, en caso de igualdad, eliminarlo mediante el comando slice.

Actualización

Si sólo pretendemos borrar los falsy values (elementos vacios o falsos), podemos recurrir a una función más sencilla extraída de los comentarios:

function cleanArray( actual ){
  var newArray = new Array();
  for( var i = 0, j = actual.length; i < j; i++ ){
      if ( actual[ i ] ){
        newArray.push( actual[ i ] );
    }
  }
  return newArray;
}
 
cleanArray( [ 1, 2, , 3, , 3, , , , , , 4, , 4, , 5, , 6 ] );
// [ 1, 2, 3, 3, 4, 4, 5, 6 ]

En este caso, en lugar de extender el objeto nativo, hemos creado una función que no acepta argumentos y que filtra todos los valores falsos para devolver un nuevo array limpio.

Más información:

http://ie.microsoft.com/testdrive/HTML5/ECMAScript5Array/Default.html

Más:

{7} Comentarios.

  1. Edward

    Hola,

    muchas gracias por el post…pero…una pregunta!!….tengo una funcion que borra el array con eso de filter(Boolean), y en Firefox todo va bien….pero….extrañamente cuando llamo esa funcion desde explorer mi codigo no corre….no sé si esto solo sea compatible con FF ?¿ , tengo IE 8 ….que podrá estar mal??

    • Carlos Benítez

      Hola Edward;
      ten en cuenta que estamos hablando de la especificación ECMAScript 5, que es relativamente reciente.
      Internet Explorer 8, sólo acepta algunas de los nuevos comandos, pero ‘filter’, es precisamente de los que no.

      Échale un vistazo a la siguiente tabla y lo compruebas tú mismo:

      http://kangax.github.com/es5-compat-table/

      Para borrar elementos vacíos de un array en IE8 o inferiores, tienes que crearte una función propia.
      Por ejemplo:

      function cleanArray( actual ){
        var newArray = new Array();
        for( var i = 0, j = actual.length; i < j; i++ ){
            if ( actual[ i ] ){
              newArray.push( actual[ i ] );
          }
        }
        return newArray;
      }
      
      cleanArray( [ 1, 2, , 3, , 3, , , , , , 4, , 4, , 5, , 6 ] ); 
      // [ 1, 2, 3, 3, 4, 4, 5, 6 ]
      
  2. Edward

    muchas gracias por tu pronta respuesta,, es que soy algo nuevo en JS entonces no estaba muy seguro de qué o porque, pero de verdad gracias, probare tu codigo, lo agradezco =)….

    Por cierto una pregunta no relacionada si de igual manera pudieras ayudarme a entender….cuando quiero llamar algo como (algunobjeto.childnodes.lenght)…cuando no hay nada……Firefox me regresa como valor «1» y Explorer si me regresa «0» ….entonces no puedo igualar alguna funcion si hago algo como «if(childnodes==0)» ……Explorer si funciona…pero FF no….como puedo resolver eso? porque sucede esa diferencia???….

    Muchas gracias nuevamente =)

  3. Edward

    hola nuevamente,

    muchas gracias pro tu codigo de limpiar arreglos con valores falsy, me ha servido de mucho….emm….regresando al tema de hasownproperty…intenté algo como obj.hasownproperty(«childnodes»)…y siempre me regresaba valor negativo….no sé si yo hiciera algo erroneo, pero ya resolví el problema….te cuanto:

    yo llamaba un DIV contenedor con un id = «div_contenedor» y mi HTML era algo como

    ( aqui había un salto de linea…)

    entonces…firefox me decia que div_contenedor.childnodes.length = 1 …..pero entonces….cuando cambie mi HTML a:

    (sin el salto de linea…)

    ahora si FF me decia que div_contenedor.childnodes.lenght = 0 …no puedo creer que ese simple espacio me hiciera dar mil vueltas…hehehe, pero ya está resuelto, de todas formas, te agradezvco mucho tu ayuda, aprendí nuevas cositas =).

    Saludos

  4. Edward

    am….en mi comentario anterior no sale hi HTML…eran unos divs…algo como:

    «(abro)» DIV id=»div_contenedor» «(cierro)»
    ( aqui había un salto de linea…)
    «(abro)» «slash / » DIV «(cierro)»

    y luego…en el otro codigo….quité el salto de linea…..:

    «(abro)» DIV id=»div_contenedor» «(cierro)»»(abro)» «slash / » DIV «(cierro)»

    • Carlos Benítez

      Hola;
      efectivamente, un salto de línea se interpreta como contenido; según el intérprete, en HTML es un br, y en Javascript es una cadena de escape. De ahí que te diese un comportamiento raro.
      Me alegro de que solucionaras tu código.
      Un saludo!

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *