Pasar una matriz como parámetro de función en JavaScript

291

Me gustaría llamar a una función usando una matriz como parámetros:

const x = ['p0', 'p1', 'p2'];
call_me(x[0], x[1], x[2]); // I don't like it

function call_me (param0, param1, param2 ) {
  // ...
}

¿Hay una mejor manera de pasar el contenido de xinto call_me()?

Robert
fuente

Respuestas:

422
const args = ['p0', 'p1', 'p2'];
call_me.apply(this, args);

Ver documentos de MDN para Function.prototype.apply().


Si el entorno es compatible con ECMAScript 6, puede utilizar un argumento extendido en su lugar:

call_me(...args);
KaptajnKold
fuente
99
Como nota al margen, si alguien quiere pasar una matriz asociativa (claves con nombre), use un objeto. Viniendo de PHP (y siempre condujo a este hilo por google), me llevó un tiempo descubrirlo. Puede pasar todo el objeto como parámetro entonces. w3schools.com/js/js_objects.asp
timhc22
¡Gracias por señalar el argumento de 'propagación'! No lo sabía.
Thomas An
@timhc: su comentario de nota al margen es intrigante, pero no puedo analizarlo (soy un novato de JavaScript que trabaja a través de un par de tutoriales). En JS, una matriz asociativa es un objeto según varios tutoriales.
NateT
@ timhc22, y cuando use el objeto json para pasar como parámetro a una función, no olvide la Destrucción de Parámetros para una mejor legibilidad
Muhammad Omer Aslam
113

¿Por qué no pasa toda la matriz y la procesa según sea necesario dentro de la función?

var x = [ 'p0', 'p1', 'p2' ]; 
call_me(x);

function call_me(params) {
  for (i=0; i<params.length; i++) {
    alert(params[i])
  }
}
Karl Johan
fuente
37
Es porque no puedo modificar call_me (). Está definido en alguna otra biblioteca y no es posible meterse con la API.
Robert
62
+1 porque a pesar de que no responde la pregunta original, probablemente sea lo que estaban buscando las más de 100K personas que vieron esta página.
Ishikawa
¿Alguien puede explicar qué está haciendo la línea "call_me (x)"? Parece que es un nombre de función sin la palabra clave de función? ¿Qué está haciendo exactamente?
nadó el
1
@swam Es una llamada a la call_mefunción. Simplemente le falta un punto y coma al final.
SantiBailors
@swam está poniendo en ejecución la función declarada call_me (params).
Julio Rodriguez
43

Suponiendo que call_me es una función global, por lo que no espera que se establezca.

var x = ['p0', 'p1', 'p2'];
call_me.apply(null, x);
plexor
fuente
7

Como @KaptajnKold había respondido

var x = [ 'p0', 'p1', 'p2' ];
call_me.apply(this, x);

Y tampoco necesita definir todos los parámetros para la función call_me. Puedes usararguments

function call_me () {
    // arguments is a array consisting of params.
    // arguments[0] == 'p0',
    // arguments[1] == 'p1',
    // arguments[2] == 'p2'
}
徐 竟 峰
fuente
44
Esta es una mala práctica ... no podrá ver qué necesita la función y todos los parámetros son opcionales si observa la función.
Robin
3

Nota esto

function FollowMouse() {
    for(var i=0; i< arguments.length; i++) {
        arguments[i].style.top = event.clientY+"px";
        arguments[i].style.left = event.clientX+"px";
    }

};

// ---------------------------

página html

<body onmousemove="FollowMouse(d1,d2,d3)">

<p><div id="d1" style="position: absolute;">Follow1</div></p>
<div id="d2" style="position: absolute;"><p>Follow2</p></div>
<div id="d3" style="position: absolute;"><p>Follow3</p></div>


</body>

puede llamar a la función con cualquier Args

<body onmousemove="FollowMouse(d1,d2)">

o

<body onmousemove="FollowMouse(d1)">
ali.by
fuente
Esto es claramente parte de la respuesta. "argumentos" definitivamente es necesario para recuperar la matriz después de la llamada. ¡Gracias!
FlorianB
2

Los argumentos de la función también pueden ser matrices:

function foo([a,b,c], d){
  console.log(a,b,c,d);
}

foo([1,2,3], 4)

por supuesto, también se puede usar propagación :

function foo(a, b, c, d){
  console.log(a, b, c, d);
}

foo(...[1, 2, 3], 4)

vsync
fuente
2

Al usar el operador spread debemos tener en cuenta que debe ser el último o único parámetro pasado. De lo contrario, fallará.

function callMe(...arr){ //valid arguments
    alert(arr);
}

function callMe(name, ...arr){ //valid arguments
    alert(arr);
}

function callMe(...arr, name){ //invalid arguments
    alert(arr);
}

Si necesita pasar una matriz como argumento inicial, puede hacerlo:

function callMe(arr, name){
    let newArr = [...arr];
    alert(newArr);
}
Naba
fuente
1

puedes usar el operador spread en una forma más básica

[].concat(...array)

en el caso de funciones que devuelven matrices pero se espera que pasen como argumentos

Ejemplo:

function expectArguments(...args){
  return [].concat(...args);
}

JSON.stringify(expectArguments(1,2,3)) === JSON.stringify(expectArguments([1,2,3]))
rman
fuente
0

La respuesta ya estaba dada, pero solo quiero dar mi pedazo de pastel. Lo que quieres lograr se llama method borrowingen el contexto de JS, que cuando tomamos un método de un objeto y lo llamamos en el contexto de otro objeto. Es bastante común tomar métodos de matriz y aplicarlos a argumentos. Dejame darte un ejemplo.

Por lo tanto, tenemos la función de hash "super" que toma dos números como argumento y devuelve una cadena hash "super safe":

function hash() {
  return arguments[0]+','+arguments[1];
}

hash(1,2); // "1,2" whoaa

Hasta ahora todo bien, pero tenemos pocos problemas con el enfoque anterior, es limitado, solo funciona con dos números, eso no es dinámico, hagamos que funcione con cualquier número y además no tiene que pasar una matriz (puede si aún insistes) Ok, basta de hablar, ¡peleemos!

La solución natural sería utilizar el arr.joinmétodo:

function hash() {
  return arguments.join();
}

hash(1,2,4,..); //  Error: arguments.join is not a function

Oh hombre. Desafortunadamente, eso no funcionará. Debido a que estamos llamando a hash (argumentos) y argumentos, el objeto es iterable y similar a una matriz, pero no es una matriz real. ¿Qué tal el enfoque a continuación?

function hash() {
  return [].join.call(arguments);
}

hash(1,2,3,4); // "1,2,3,4" whoaa

El truco se llama method borrowing.

Tomamos prestado un joinmétodo de una matriz regular [].join.y lo usamos [].join.callpara ejecutarlo en el contexto de arguments.

Por que funciona

Eso es porque el algoritmo interno del método nativo arr.join(glue)es muy simple.

Tomado de la especificación casi "tal cual":

Let glue be the first argument or, if no arguments, then a comma ",".
Let result be an empty string.
Append this[0] to result.
Append glue and this[1].
Append glue and this[2].
Do so until this.length items are glued.
Return result.

Entonces, técnicamente toma esto y une esto [0], esto [1] ... etc. Está escrito intencionalmente de una manera que permite cualquier matriz como esta (no es una coincidencia, muchos métodos siguen esta práctica). Por eso también funciona conthis=arguments.

Humoyun Ahmad
fuente