Passando argumentos adiante para outra função javascript

386

Eu tentei o seguinte sem sucesso:

function a(args){
    b(arguments);
}

function b(args){
    // arguments are lost?
}

a(1,2,3);

Na função a, posso usar a palavra-chave argumentos para acessar uma matriz de argumentos, na função b estes são perdidos. Existe uma maneira de passar argumentos para outra função javascript como eu tento fazer?

Anders Nygaard
fonte
3
@ BobStein-VisiBone concordou. Além disso, observe que, na verdade,arguments não é uma matriz (mas um objeto que implementa a semântica semelhante a uma matriz ) e, portanto, não está totalmente claro à primeira vista se ela pode ser usada da mesma maneira que uma matriz real.
Jules
@Jules ainda vota para reabrir depois de todos esses anos. Qual é o distintivo para queimar o valioso trabalho de outras pessoas? Muitos deles para dar a volta.
Bob Stein

Respostas:

542

Use .apply()para ter o mesmo acesso à argumentsfunção in b, assim:

function a(){
    b.apply(null, arguments);
}
function b(){
   alert(arguments); //arguments[0] = 1, etc
}
a(1,2,3);​

Você pode testá-lo aqui .

Nick Craver
fonte
21
@Brett - Você pode copiá-lo em uma matriz e manipulá-lo antes de transmiti-lo, por exemplo:var copy = [].slice.call(arguments); <remove what you want> myFunc.apply(this, copy);
Nick Craver
18
mas usando applycomo isso pode estragar o escopo de b(se é alguma função interna de um objeto, por exemplo)
vsync
3
@vsync bom ponto, mas o problema é fácil de resolver: passar o objeto como o primeiro argumento a ser aplicado.
Tad Lispy
11
não faz sentido usar "argumentos" e "argumentos" juntos ...
cara
3
Mas então o "this" pode ser alterado para algo diferente do original de b, this.
trusktr
223

Operador de propagação

O operador de spread permite que uma expressão seja expandida em locais onde vários argumentos (para chamadas de função) ou vários elementos (para literais de matriz) são esperados.

O ECMAScript ES6 adicionou um novo operador que permite fazer isso de uma maneira mais prática: ... Operador de propagação .

Exemplo sem usar o applymétodo:

function a(...args){
  b(...args);
  b(6, ...args, 8) // You can even add more elements
}
function b(){
  console.log(arguments)
}

a(1, 2, 3)

Note Esse trecho retorna um erro de sintaxe se o seu navegador ainda usa o ES5.

Nota do Editor: Uma vez que os usos do snippet console.log(), você deve abrir JS consola do seu navegador para ver o resultado - não haverá nenhum resultado na página.

Ele exibirá este resultado:

Imagem do exemplo de argumentos do operador Spread

Em resumo, o operador de dispersão pode ser usado para diferentes propósitos se você estiver usando matrizes; portanto, também pode ser usado para argumentos de função. Você pode ver um exemplo semelhante explicado nos documentos oficiais: Parâmetros de descanso

Walter Chapilliquen - wZVanG
fonte
6
Este é um operador muito bom e estou realmente ansioso para usá-lo. No entanto, isso não vai acontecer ainda. O único navegador que já suporta o operador de propagação é o FF no momento. Consulte a tabela de compatibilidade para obter dados completos e atualizados: kangax.github.io/compat-table/es6/#spread_%28...%29_operator
TMG
10
Por que não deveria ser usado? É relativamente fácil transpilar com o babel, você obtém todos os novos recursos e muito mais compatibilidade com navegadores antigos.
Adgelbfish
Isso é melhor que a primeira solução porque funciona na função definida com o operador de seta.
sarfata
Você não precisa ...argsda afunção. Você pode apenas fazer uma função sem argumentos e passá-los para bcom...arguments
cronoklee
11
Para quem lê esta resposta: Ao contrário do comentário de @ cronoklee, especificar explicitamente ...argscomo aentrada pode ser importante se você tiver funções aninhadas.
Arshia001 26/05/19
81

A explicação que nenhuma das outras respostas fornece é que os argumentos originais ainda estão disponíveis, mas não na posição original no argumentsobjeto.

O argumentsobjeto contém um elemento para cada parâmetro real fornecido para a função. Quando você liga para avocê fornecer três argumentos: os números 1, 2e,3 . Então, argumentscontém [1, 2, 3].

function a(args){
    console.log(arguments) // [1, 2, 3]
    b(arguments);
}

Quando você chama b, no entanto, passa exatamente um argumento: ao argumentsobjeto de. Então argumentscontém [[1, 2, 3]](ou seja, um elemento, que éa o argumentsobjeto de s , que possui propriedades que contêm os argumentos originais para a).

function b(args){
    // arguments are lost?
    console.log(arguments) // [[1, 2, 3]]
}

a(1,2,3);

Como o @Nick demonstrou, você pode usar applypara fornecer um argumentsobjeto definido na chamada.

O seguinte alcança o mesmo resultado:

function a(args){
    b(arguments[0], arguments[1], arguments[2]); // three arguments
}

Mas applyé a solução correta no caso geral.

Wayne
fonte
Você sempre deve passar thispara apply?
Flimm 9/07/2015
11
@ Flimm - sim, como os argumentos são o segundo argumento, deve haver algo para o primeiro argumento (pode ser nulo ).
RobG
0

tente isso

function global_func(...args){
  for(let i of args){
    console.log(i)
  }
}


global_func('task_name', 'action', [{x: 'x'},{x: 'x'}], {x: 'x'}, ['x1','x2'], 1, null, undefined, false, true)




//task_name
//action
//(2) [{...},
//    {...}]
//    {
//        x:"x"
//    }
//(2) [
//        "x1",
//        "x2"
//    ]
//1
//null
//undefined
//false
//true
//func
Jaber Alshami
fonte