Passando gli argomenti in avanti ad un'altra funzione JavaScript


386

Ho provato quanto segue senza successo:

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

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

a(1,2,3);

Nella funzione a, posso usare la parola chiave argomenti per accedere a una serie di argomenti, nella funzione b questi vengono persi. Esiste un modo per passare argomenti a un'altra funzione javascript come cerco di fare?


3
@ BobStein-VisiBone concordato. Inoltre, si noti che in realtàarguments non è un array (ma piuttosto un oggetto che implementa una semantica simile ad un array ) e quindi non è del tutto chiaro a prima vista se può essere usato allo stesso modo di un array reale.
Jules il

@Jules vota ancora per riaprire dopo tutti questi anni. Qual è il distintivo per bruciare il prezioso lavoro degli altri? Molti di quelli che vanno in giro.
Bob Stein,

Risposte:


542

Utilizzare .apply()per avere lo stesso accesso a argumentsin funzione b, in questo modo:

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

Puoi provarlo qui .


21
@Brett - Puoi copiarlo in un array e poi manipolarlo prima di passarlo, ad esempio:var copy = [].slice.call(arguments); <remove what you want> myFunc.apply(this, copy);
Nick Craver

18
ma l'utilizzo in applyquesto modo potrebbe rovinare l'ambito di b(se per esempio è una funzione interna di un oggetto)
vsync,

3
@vsync buon punto, ma il problema è facile da risolvere: passare l'oggetto come primo argomento da applicare.
Tad Lispy,

11
non ha senso usare "args" e "argomenti" insieme ...
amico

3
Ma poi il "questo" potrebbe essere cambiato in qualcosa di diverso dal b originale di questo.
trusktr,

223

Operatore di diffusione

L'operatore spread consente di espandere un'espressione in punti in cui sono previsti più argomenti (per chiamate di funzione) o più elementi (per valori letterali di array).

ECMAScript ES6 ha aggiunto un nuovo operatore che ti consente di farlo in modo più pratico: ... Spread Operator .

Esempio senza utilizzare il applymetodo:

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 Questo frammento restituisce un errore di sintassi se il browser utilizza ancora ES5.

Nota del redattore: poiché lo snippet viene utilizzato console.log(), è necessario aprire la console JS del browser per visualizzare il risultato , senza risultati in-page.

Verrà visualizzato questo risultato:

Immagine dell'esempio degli argomenti dell'operatore Spread

In breve, l'operatore di diffusione può essere utilizzato per scopi diversi se si utilizzano array, quindi può essere utilizzato anche per argomenti di funzione, è possibile vedere un esempio simile spiegato nei documenti ufficiali: Parametri di riposo


6
Questo è un operatore molto gentile e non vedo davvero l'ora di usarlo. Tuttavia, non accadrà ancora. Al momento, l'unico browser che supporta già l'operatore di diffusione è FF. Consulta la tabella di compatibilità per i dati completi e aggiornati: kangax.github.io/compat-table/es6/#spread_%28...%29_operator
TMG

10
Perché non dovrebbe essere usato? È relativamente facile da compilare con Babel, ottieni tutte le nuove funzionalità e molta più compatibilità con i browser più vecchi.
adgelbfish,

È meglio della prima soluzione perché funziona nella funzione definita con l'operatore freccia.
sarfata,

Non è necessario ...argsnella afunzione. Puoi semplicemente fare una funzione senza argomenti e passarli a bcon...arguments
cronoklee

1
Per chiunque legga questa risposta: Contrariamente al commento di @ cronoklee, specificare esplicitamente ...argscome ainput può essere importante se si hanno funzioni nidificate.
Arshia001,

81

La spiegazione che nessuna delle altre risposte fornisce è che gli argomenti originali sono ancora disponibili, ma non nella posizione originale argumentsnell'oggetto.

L' argumentsoggetto contiene un elemento per ciascun parametro effettivo fornito alla funzione. Quando si chiama afornite tre argomenti: i numeri 1, 2e, 3. Quindi, argumentscontiene [1, 2, 3].

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

Quando chiami b, però, passi esattamente un argomento: l a' argumentsoggetto. Quindi argumentscontiene [[1, 2, 3]](cioè un elemento, che è l a' argumentsoggetto, che ha proprietà contenenti gli argomenti originali a a).

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

a(1,2,3);

Come dimostrato da @Nick, è possibile utilizzare applyper fornire un argumentsoggetto set nella chiamata.

Di seguito si ottiene lo stesso risultato:

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

Ma applyè la soluzione corretta nel caso generale.


Dovresti sempre passare thisa apply?
Flimm,

1
@ Flimm: sì, poiché gli argomenti sono il secondo argomento, deve esserci qualcosa per il primo argomento (può essere nullo ).
RobG

0

prova questo

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.