Estoy tratando de crear una función que imite Array.prototype.push. Toma un número variable de argumentos y los empuja a una matriz específica. He logrado hacer esto con el siguiente código:

var array=[];
function append(){
    for(var i=0;i<arguments.length;i++)
        array.push(arguments[i]);
}

Ahora mi pregunta es: ¿puedo reescribir la función append sin usar "for loop"? Gracias por adelantado.

2
cssGEEK 9 may. 2016 a las 17:26

4 respuestas

La mejor respuesta

Puedes usar Array.prototype.push.apply

function append(){
    // make arguments an array
    var args = Array.prototype.slice.call(arguments);
    // return the number of elements pushed in the array
    return Array.prototype.push.apply(array, args);
}

Entonces, ¿qué está pasando aquí con args? Usamos Array.prototype.slice.call con argumentos, con el propósito de hacer arguments una matriz, porque es un objeto especial. Function.prototype.call se usa para llamar a una función con un contexto específico (también conocido como this), y luego los argumentos para llamar a la función con (separados por comas). Convenientemente, parece que slice() mira la propiedad length del contexto this, y arguments también tiene uno, y cuando no está vacío, tiene propiedades de 0 a {{ X9}}, que permite slice copiar arguments en una nueva matriz.

1
axelduch 9 may. 2016 a las 14:38

En realidad, honestamente creo que el impulso debe redefinirse para el JS funcional, ya que su valor de retorno es la longitud de la matriz resultante y la mayoría de las veces es inútil. Por ejemplo, cuando es necesario empujar un valor y pasar una matriz como parámetro a una función, no puede hacerlo en línea y las cosas se complican. En cambio, me gustaría que devuelva una referencia a la matriz a la que se llama o incluso a una nueva matriz de donde puedo obtener la información de longitud de todos modos. Mi nueva propuesta de empuje sería la siguiente;

Array.prototype.push = function(...args) {
                         return args.reduce(function(p,c) {
                                              p[p.length] = c;
                                              return p
                                            }, this)
                       };

Devuelve una referencia perfecta a la matriz a la que está llamado.

0
Redu 9 may. 2016 a las 15:09

Si necesita obtener una matriz de argumentos, debe usar la función de división de Array en un objeto de argumentos, y la convertirá en una matriz JavaScript estándar:

var array = Array.prototype.slice.call(arguments);
2
alexmac 9 may. 2016 a las 14:38

Puede volver a escribir esto sin un bucle for, pero debe usar un bucle de algún tipo (está trabajando con varios elementos, es una necesidad).

Si tiene acceso a ES6 o Babel, usaría algo como:

function append(...args) {
  return array.concat(args);
}

Sin ES6, debe evitar el hecho de que arguments no es una matriz real. Todavía puede aplicarle la mayoría de los métodos de matriz, accediendo a ellos a través del prototipo Array. Convertir arguments en una matriz es bastante fácil, entonces puede concat los dos:

function append() {
  var args = Array.prototype.map.call(arguments, function (it) {
    return it;
  });
  return array.concat(args);
}

Tenga en cuenta que ninguno de estos modificará el array global, pero devolverá una nueva matriz con los valores combinados que se pueden usar solos o asignados de nuevo a array . Esto es algo más fácil y más robusto que intentar trabajar con push, si está dispuesto a array = append(...).

0
ssube 9 may. 2016 a las 14:29