Contenido

Array.every(), por cada elemento

3 Dic

+ 5

Según la especificación de Javascript 1.6, los objetos tipo Array disponen de un método llamado every(), que nos permite hacer que por cada elemento de un Array ejecutemos una acción, devolviéndonos false en caso de que la acción que pasamos no devuelva true en alguno de los elementos.

Para los navegadores que incorporan este método, existe un sistema para extender los Array con este método.

if (!Array.prototype.every){
  Array.prototype.every = function(fun /*, thisp*/){
    var len = this.length;
    if (typeof fun != "function")
      throw new TypeError();

    var thisp = arguments[1];
    for (var i = 0; i < len; i++){
      if (i in this && !fun.call(thisp, this[i], i, this))
         return false;
    }
    return true;
  };
}

También podemos añadirla mediante el uso de extend() de la siguiente forma.

extend({
    every: function(fun /*, thisp*/) {
    var len = this.length;
    if (typeof fun != "function")
      throw new TypeError();

    var thisp = arguments[1];
    for (var i = 0; i < len; i++)
    {
      if (i in this &&
          !fun.call(thisp, this[i], i, this))
        return false;
    }
    return true;
  }
},Array.prototype);

Yo hace unos días, haciendo unas pruebas para una cosilla que estoy desarrollando implementé mi propia versión, sin conocer la existencia de esta y la funcionalidad es diferente ya que interpreté el every() como su traducción al castellano cada(), y mi implementación aplica una funcionalidad cada X elementos.

extend({
  every: function(num, fun){
     if (typeof fun != "function") throw new TypeError();
       for (var i = 0; i < this.length; i++) {
         if (i in this && i%num == 0) fun.call(arguments[1], this[i], i)
       }
    return this;
 }
}, Array.prototype);

De esta forma, podemos usarlo de la siguiente forma.

[1,2,3,4,5,6].every(2, function(el){
   alert(el);
});
  • tambien podrias hacer que si no le pasas una funcion te devuelva un nuevo array donde haya filtrado los elementos cada X, algo así:

    
    extend({
    	every: function(num, fun){
    
    	 if (typeof fun != "function"){
    		var nuevoArray = [];
    		for (var i = 0; i < this.length; i++) {
    			if (i in this && i%num == 0){
    				nuevoArray.push(this[i]);
    			}
    		}
    		return nuevoArray;
    	 }
    	 else{
    		for (var i = 0; i < this.length; i++) {
    			if (i in this && i%num == 0){
    				fun.call(arguments[1], this[i], i);
    			}
    		}
    	 }
    	 
    	return this;
    	}
    }, Array.prototype);
    

    (no se si el tag code es el correcto)

    ahora [111,222,333,444,555,666].every(2) devolveria [111,333,555]

  • @gbt29: Buena idea, aunque la he podido reducir un poco.

    
    extend({
           every: function(num, fun){
                   var nuevoArray = [];
                   for (var i = 0; i < this.length; i++) {
                           if (i in this && i%num == 0)
                                   nuevoArray.push(this[i]);
    			if (typeof fun == 'function')
    					fun.call(arguments[1], this[i], i);
                   }
                   return (typeof fun == 'function') ? this : nuevoArray;
           }
    }, Array.prototype);
    
    
  • encontre un problema, cuando extendes la clase array y agregas metodos cuando haces un for in en un array te larga tambien los metodos agregados si es que el nombre de este no existe de forma nativa, osea una vez que extendiste y agregaste every

    for( var i in [1, 2, 3] ){
    alert(i);
    }
    alerta 1, 2, 3, every

    (solo en ie y los navegadores que no tiene every por defecto)

    creo que la solucion va a ser extender array y agregar el metodo each que recorra cada uno y que se fije si no es un metodo de la clase array

  • hice el metodo each y algunos mas:

    
    extend({
    	every: function(num, fun){
    
    	 if (typeof fun != "function"){
    		var nuevoArray = [];
    		for (var i = 0; i < this.length; i++) {
    			if (i in this && i%num == 0){
    				nuevoArray.push(this[i]);
    			}
    		}
    		return nuevoArray;
    	 }
    	 else{
    		for (var i = 0; i < this.length; i++) {
    			if (i in this && i%num == 0){
    				fun.call(arguments[1], this[i], i);
    			}
    		}
    	 }
    	 
    	return this;
    	},
    	
    	randomize: function(){
    		return ( Math.floor( Math.random() * ( this[1] - this[0] + 1 ) + ( this[0] ) ) );
    	},
    	
    	random: function(){
    		return this[[0, this.length - 1].randomize()];
    	},
    	
    	mix: function(){
    		var nuevoArray = [];
    		while(nuevoArray.length != this.length){
    			var rand = [0, this.length - 1].randomize();
    			if( this[rand] != "already taken" ){
    				nuevoArray.push( this[rand] );
    				this[rand] = "already taken";
    			}
    		}
    		return nuevoArray;
    	},
    	
    	range: function(){
    		var nuevoArray = [];
    		for(var n = this[0]; n < this[1]; n++) nuevoArray[n]=n;
    		return nuevoArray;
    	},
    	
    	each: function(fun){
    		for( var i in this ){
    			if( !Array.prototype[i] ){
    				fun.call(this, this[i], i);
    			}
    		}
    	}
    }, Array.prototype);
    

    array.randomize:
    [5, 10].randomize() // devuelve un numero random entre 5 y 10

    array.random:
    [1, 2, 3].random() // devuelve un valor random del array, que puede ser 1, 2 o 3

    array.mix:
    [11, 22, 33].mix() // mezcla el array y devuelve por ejemplo 11, 33, 22

    array.range:
    [5, 10].range() // devuelve un array con todos lo numeros entre 5 y 10 ( [5,6,7,8,9,10] )
    [5, 10, 2].range() // equivale a [5, 10].range().every(2)

    array.each:

    [11, 22, 33].each(function( valor, index ){
    alert(valor); // alerta 11, 22 y 33
    alert(index); // alerta 0, 1, 2
    });

  • anieto ese fue un comentario repetido, lo volvi a postear porque no aparecia, y reciend despues lei donde dice «Si tu comentario no aparece, puede ser que akismet lo haya capturado, cada día lo reviso y lo coloco en su lugar.» perdon ^^ si queres borra el repetido (el anterior a este)

Comentar

#

Me reservo el derecho de eliminar y/o modificar los comentarios que contengan lenguaje inapropiado, spam u otras conductas no apropiadas en una comunidad civilizada. Si tu comentario no aparece, puede ser que akismet lo haya capturado, cada día lo reviso y lo coloco en su lugar. Siento las molestias.