Passando uma matriz como um parâmetro de função em JavaScript

291

Eu gostaria de chamar uma função usando uma 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 ) {
  // ...
}

Existe uma maneira melhor de passar o conteúdo do xpara call_me()?

Robert
fonte

Respostas:

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

Consulte os documentos MDN para Function.prototype.apply().


Se o ambiente suportar o ECMAScript 6, você poderá usar um argumento de dispersão :

call_me(...args);
KaptajnKold
fonte
9
Como uma observação lateral, se alguém quiser transmitir uma matriz associativa (chaves nomeadas), use um objeto. Vindo do PHP (e sempre levado a esse segmento pelo google), demorei um pouco para descobrir. Você pode passar o objeto inteiro como parâmetro então. Você
usar o seguinte
Obrigado por apontar o argumento 'spread'! Não sabia disso.
Thomas Um
@timhc - o comentário da nota lateral é intrigante, mas não consigo analisá-lo (eu sou um noob javascript trabalhando em alguns tutoriais). Em JS, uma matriz associativa é um objeto de acordo com vários tutoriais.
NateT 28/08/18
@ timhc22, e quando usando o objeto json para passar como um parâmetro para uma função não faça esquecer a destruição de parâmetros para melhor legibilidade
Muhammad Omer Aslam
113

Por que você não passa a matriz inteira e a processa conforme necessário dentro da função?

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

function call_me(params) {
  for (i=0; i<params.length; i++) {
    alert(params[i])
  }
}
Karl Johan
fonte
37
É porque eu não posso modificar call_me (). Está definido em alguma outra biblioteca e não é possível mexer com a API.
Robert
62
+1 porque, embora não responda à pergunta original, é provavelmente o que as mais de 100 mil pessoas que visualizaram esta página estavam procurando.
Ishikawa
Alguém pode explicar o que a linha "call_me (x)" está fazendo? Parece que é um nome de função sem a palavra-chave function? O que exatamente está fazendo?
nadou
1
@swam É uma chamada para a call_mefunção. Falta apenas um ponto e vírgula no final.
SantiBailors
@swam está colocando em execução a função call_me (params) declarada.
Julio Rodriguez
43

Supondo que call_me seja uma função global, você não espera que isso seja definido.

var x = ['p0', 'p1', 'p2'];
call_me.apply(null, x);
plexer
fonte
41

No padrão ES6, há um novo operador de spread ... que faz exatamente isso.

call_me(...x)

É suportado por todos os principais navegadores, exceto o IE.

O operador de propagação pode fazer muitas outras coisas úteis, e a documentação vinculada faz um bom trabalho em mostrar isso.

BoltKey
fonte
7

Como @KaptajnKold respondeu

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

E você também não precisa definir todos os parâmetros para a função call_me. Você pode apenas usararguments

function call_me () {
    // arguments is a array consisting of params.
    // arguments[0] == 'p0',
    // arguments[1] == 'p1',
    // arguments[2] == 'p2'
}
徐 竟 峰
fonte
4
Essa é uma prática tão ruim ... você não poderá ver o que a função precisa e todos os parâmetros são opcionais se você olhar para a função.
31416 Robin
3

Observe isso

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>

pode chamar a função com qualquer Args

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

ou

<body onmousemove="FollowMouse(d1)">
ali.by
fonte
Isso é claramente parte da resposta. Definitivamente, "argumentos" é necessário para recuperar a matriz após a chamada. Obrigado!
FlorianB
2

Os argumentos da função também podem ser matrizes:

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

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

é claro que também se pode usar spread :

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

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

vsync
fonte
2

Ao usar o operador spread, devemos observar que deve ser o último ou o único parâmetro passado. Senão falhará.

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

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

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

Se você precisar passar uma matriz como argumento inicial, poderá:

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

você pode usar o operador spread de uma forma mais básica

[].concat(...array)

no caso de funções que retornam matrizes, mas espera-se que sejam transmitidas como argumentos

Exemplo:

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

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

A resposta já foi dada, mas eu só quero dar meu pedaço de bolo. O que você deseja alcançar é chamadomethod borrowing no contexto de JS, quando pegamos um método de um objeto e o chamamos no contexto de outro objeto. É bastante comum usar métodos de matriz e aplicá-los a argumentos. Deixe-me lhe dar um exemplo.

Portanto, temos a função de hash "super", que recebe dois números como argumento e retorna a string de hash "super segura":

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

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

Até aí tudo bem, mas temos pouco problema com a abordagem acima, ela é restrita, funciona apenas com dois números, que não é dinâmico, vamos fazê-la funcionar com qualquer número e, além disso, você não precisa passar uma matriz (você pode se você ainda insistir). Ok, chega de conversa, vamos lutar!

A solução natural seria usar o arr.joinmétodo:

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

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

Oh cara. Infelizmente, isso não vai funcionar. Como estamos chamando hash (argumentos) e objeto de argumentos, é iterável e semelhante a um array, mas não um array real. E a abordagem abaixo?

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

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

O truque é chamado method borrowing.

Nós emprestamos um joinmétodo de uma matriz regular [].join.e usamos [].join.callpara executá-lo no contexto dearguments .

Por que isso funciona?

Isso ocorre porque o algoritmo interno do método nativo arr.join(glue) ocorre é muito simples.

Retirado da especificação quase "como está":

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.

Então, tecnicamente, é preciso isso e une esse [0], esse [1] ... etc juntos. É intencionalmente escrito de uma maneira que permite qualquer array como este (não é uma coincidência, muitos métodos seguem essa prática). É por isso que também funciona comthis=arguments.

Humoyun Ahmad
fonte