Restituire più valori in JavaScript?


847

Sto cercando di restituire due valori in JavaScript . È possibile?

var newCodes = function() {  
    var dCodes = fg.codecsCodes.rs;
    var dCodes2 = fg.codecsCodes2.rs;
    return dCodes, dCodes2;
};

puoi risolverlo usando i callback, se sei disposto a farlo, vedi la mia risposta. La gente dimentica che puoi "restituire più valori" facilmente con JS, usando le tuple o anche: callback!
Alexander Mills,

16
Le risposte sono obsolete. Ora è possibile 2ality.com/2014/06/es6-multiple-return-values.html
Erel Segal-Halevi

3
Tecnicamente stai ancora restituendo un singolo oggetto / array, è solo la decostruzione che è più semplice in ES6.
Andrea Bergonzo,

Risposte:


1301

No, ma potresti restituire un array contenente i tuoi valori:

function getValues() {
    return [getFirstValue(), getSecondValue()];
}

Quindi puoi accedervi in ​​questo modo:

var values = getValues();
var first = values[0];
var second = values[1];

Con la sintassi ECMAScript 6 più recente *, puoi anche destrutturare il valore restituito in modo più intuitivo:

const [first, second] = getValues();

Se vuoi mettere "etichette" su ciascuno dei valori restituiti (più facile da mantenere), puoi restituire un oggetto:

function getValues() {
    return {
        first: getFirstValue(),
        second: getSecondValue(),
    };
}

E per accedervi:

var values = getValues();
var first = values.first;
var second = values.second;

O con la sintassi ES6:

const {first, second} = getValues();

* Vedi questa tabella per la compatibilità del browser. Fondamentalmente, tutti i browser moderni a parte IE supportano questa sintassi, ma puoi compilare il codice ES6 fino a JavaScript compatibile con IE al momento della compilazione con strumenti come Babel .


151
Oppure puoi restituire un oggetto: return {dCodes : dCodes, dCodes2 : dCodes2};per facilitare il riferimento.
Intelekshual,

10
potresti persino restituire un oggetto {: dCodes: dCodes, dCodes2: dCodes2} funzionalmente lo stesso ma quando fai riferimento all'oggetto restituito hai un codice un po 'più leggibile come obj.dCodes e obj.dCodes2 vs obj [0] e obj [1 ]
Jonathan S.

1
@alexela Sicuro che puoi semplicemente usare var dCodes = newCodes (). dCodes; var dCodes2 = newCodes (). dCodes2 Tuttavia, si chiamerà due volte la funzione che potrebbe essere uno spreco di risorse se è complessa.
Vadim Kirilchuk,

12
@VadimKirilchuk Non è necessario chiamarlo due volte con un incarico distruttivo - ad es. const { dCodes, dCodes2 } = newCodes();
Taylor Edmiston,

7
come dicevano altre risposte (e commenti impliciti), ES6 offre alcune opzioni qui. 3 per l'esattezza: (1) la stenografia della proprietà dell'oggetto return {dCodes, dCodes2} funziona esattamente come menzionata con @Intelekshual e (2) usando la stessa funzione si potrebbe semplicemente accedervi con array destrutturanti [dCodes, dCodes2] = newCodes()o (3) oggetti ({dCodes, dCodes2} = newCodes())(non è necessario usare una dichiarazione lì @Taylor , sebbene a varsarebbe più appropriato per l'attuale esempio di Sasha).
Cregox,

241

Puoi farlo da Javascript 1.7 in poi usando "incarichi di destrutturazione" . Si noti che questi non sono disponibili nelle versioni JavaScript precedenti (ovvero, né con la terza o la quinta edizione di ECMAScript).

Ti consente di assegnare a 1+ variabili contemporaneamente:

var [x, y] = [1, 2];
x; // 1
y; // 2

// or

[x, y] = (function(){ return [3, 4]; })();
x; // 3
y; // 4

È inoltre possibile utilizzare la destrutturazione degli oggetti combinata con la scorciatoia del valore della proprietà per nominare i valori restituiti in un oggetto e selezionare quelli desiderati:

let {baz, foo} = (function(){ return {foo: 3, bar: 500, baz: 40} })();
baz; // 40
foo; // 3

E a proposito, non lasciarti ingannare dal fatto che ECMAScript ti consente return 1, 2, .... Ciò che accade realmente non è ciò che potrebbe sembrare. Un'espressione in return - 1, 2, 3- è altro che un operatore virgola applicato a letterali numerici ( 1, 2e 3) in sequenza, che alla fine restituisce il valore della sua ultima espressione - 3. Ecco perché return 1, 2, 3è funzionalmente identico a nient'altro che return 3.

return 1, 2, 3;
// becomes
return 2, 3;
// becomes
return 3;

1
Cosa strana e interessante sull'ultimo esempio: per un function foo(){return 1,2,3;}fare le console.log([].push(foo()))stampe 1.
Meredith,

@ AurélienOoms mi sono reso conto più tardi. Grazie
Meredith il

1
perché var [x, y] = [1, 2]; X; // 1 anno; // 2 questo non funziona in Chrome? solleva un errore; Errore di riferimento: lato sinistro non valido nell'incarico
Naveen Agarwal

1
Chrome v49 è stato rilasciato una settimana fa con il supporto di "incarichi di destrutturazione" pronti all'uso.
Eugene Kulabuhov

1
Questa dovrebbe essere la risposta accettata: la nuova destrutturazione è un ottimo modo per farlo.
Jez,

68

Restituisci un oggetto letterale

function newCodes(){
    var dCodes = fg.codecsCodes.rs; // Linked ICDs  
    var dCodes2 = fg.codecsCodes2.rs; //Linked CPTs       
    return {
        dCodes: dCodes, 
        dCodes2: dCodes2
    };  
}


var result = newCodes();
alert(result.dCodes);
alert(result.dCodes2);

@SeanKinsey Mi piace questa soluzione. Potrebbe essere utile per me. Una domanda, ci dovrebbe essere bisogno di una funzione per il ritorno sarebbe ogni caso di risultato ( result1 .. valoreN ) ottenere la propria copia della funzione o ci sarebbe resuse del codice funzione? (Non so come ho potuto provare per questo.) TIA.
Karl,

44

Da ES6 puoi farlo

let newCodes = function() {  
    const dCodes = fg.codecsCodes.rs
    const dCodes2 = fg.codecsCodes2.rs
    return {dCodes, dCodes2}
};

let {dCodes, dCodes2} = newCodes()

L'espressione di ritorno {dCodes, dCodes2}è una scorciatoia del valore della proprietà ed è equivalente a questa {dCodes: dCodes, dCodes2: dCodes2}.

Questa assegnazione sull'ultima riga è chiamata assegnazione che distrugge l'oggetto . Estrae il valore della proprietà di un oggetto e lo assegna a una variabile con lo stesso nome. Se desideri assegnare valori di ritorno a variabili di nome diverso, puoi farlo in questo modolet {dCodes: x, dCodes2: y} = newCodes()


27

Ecmascript 6 include "assegnazioni destrutturanti" (come menzionato da kangax), quindi in tutti i browser (non solo Firefox) sarai in grado di acquisire una matrice di valori senza dover creare una matrice o un oggetto nominati al solo scopo di catturarli.

//so to capture from this function
function myfunction()
{
 var n=0;var s=1;var w=2;var e=3;
 return [n,s,w,e];
}

//instead of having to make a named array or object like this
var IexistJusttoCapture = new Array();
IexistJusttoCapture = myfunction();
north=IexistJusttoCapture[0];
south=IexistJusttoCapture[1];
west=IexistJusttoCapture[2];
east=IexistJusttoCapture[3];

//you'll be able to just do this
[north, south, west, east] = myfunction(); 

Puoi già provarlo su Firefox!


24

Un altro aspetto degno di nota per la sintassi appena introdotta (ES6) è l'uso della scorciatoia per la creazione di oggetti oltre a distruggere l'assegnazione.

function fun1() {
  var x = 'a';
  var y = 'b';
  return { x, y, z: 'c' };
  // literally means { x: x, y: y, z: 'c' };
}

var { z, x, y } = fun1(); // order or full presence is not really important
// literally means var r = fun1(), x = r.x, y = r.y, z = r.z;
console.log(x, y, z);

Questa sintassi può essere polifillata con babel o altri polyfiller js per browser meno recenti, ma fortunatamente ora funziona nativamente con le versioni recenti di Chrome e Firefox.

Ma quando si crea un nuovo oggetto, l'allocazione di memoria (e l'eventuale caricamento di gc) sono coinvolti qui, non aspettarsi molte prestazioni da esso. JavaScript non è il miglior linguaggio per lo sviluppo di cose altamente ottimali, ma se è necessario, puoi considerare di mettere il tuo risultato sull'oggetto circostante o su tali tecniche che di solito sono trucchi prestazionali comuni tra JavaScript, Java e altri linguaggi.


Che non funziona ancora su IE o Edge, volevo solo notare.
user1133275,

Lo sto usando da un bel po '... è più veloce / fluido usare un array ed evitare di costruire un oggetto, se possibile, come mostrato da @ user3015682.
dkloke,

18

Il modo migliore per questo è

function a(){
     var d=2;
     var c=3;
     var f=4;
     return {d:d,c:c,f:f}
}

Quindi utilizzare

a().f

ritorno 4

in ES6 è possibile utilizzare questo codice

function a(){
      var d=2;
      var c=3;
      var f=4;
      return {d,c,f}
}

Quindi eseguire nuovamente la funzione per ogni variabile? Questo non è l'approccio migliore.
Elia Iliashenko,

questa funzione restituisce valore multiplo, forse non è l'approccio migliore.
Behnam Mohammadi,

Ogni volta che l'interprete incontra un () esegue nuovamente la funzione. Quindi, var f = a (). F; var c = a (). c; var d = a (). d; lancerà un () tre volte, il che è soggetto a perdita di prestazioni. L'approccio migliore sarebbe var result = a (); var f = risultato.f; ecc.
Elia Iliashenko,

1
ok per prestazioni migliori, puoi mantenere il valore di una variabile e usarla, ad esempio var result = a (); e usa il valore result.d o result.c e result.f, quindi esegui contemporaneamente una funzione ().
Behnam Mohammadi,

9

Oltre a restituire un array o un oggetto come altri hanno raccomandato, puoi anche utilizzare una funzione di raccolta (simile a quella che si trova in The Little Schemer ):

function a(collector){
  collector(12,13);
}

var x,y;
a(function(a,b){
  x=a;
  y=b;
});

Ho fatto un test jsperf per vedere quale dei tre metodi è più veloce. L'array è più veloce e il collector è più lento.

http://jsperf.com/returning-multiple-values-2


In genere collectorviene chiamato continuatione la tecnica si chiama CPS
ceving

7

In JS, possiamo facilmente restituire una tupla con un array o un oggetto, ma non dimenticare! => JS è un callbacklinguaggio orientato, e qui c'è un piccolo segreto per "restituire più valori" che nessuno ha ancora menzionato, prova questo:

var newCodes = function() {  
    var dCodes = fg.codecsCodes.rs;
    var dCodes2 = fg.codecsCodes2.rs;
    return dCodes, dCodes2;
};

diventa

var newCodes = function(fg, cb) {  
    var dCodes = fg.codecsCodes.rs;
    var dCodes2 = fg.codecsCodes2.rs;
    cb(null, dCodes, dCodes2);
};

:)

bam! Questo è semplicemente un altro modo di risolvere il tuo problema.


6

Aggiungendo le parti importanti mancanti per rendere questa domanda una risorsa completa, in quanto ciò risulta nei risultati di ricerca.

Distruzione di oggetti

Nella distruzione degli oggetti, non è necessario utilizzare lo stesso valore chiave del nome della variabile, è possibile assegnare un nome di variabile diverso definendolo come di seguito:

const newCodes = () => {  
    let dCodes = fg.codecsCodes.rs;
    let dCodes2 = fg.codecsCodes2.rs;
    return { dCodes, dCodes2 };
};

//destructuring
let { dCodes: code1, dCodes2: code2 } = newCodes();

//now it can be accessed by code1 & code2
console.log(code1, code2);

Ristrutturazione di array

Nella distruzione dell'array, è possibile saltare i valori non necessari.

const newCodes = () => {  
    //...
    return [ dCodes, dCodes2, dCodes3 ];
};

let [ code1, code2 ] = newCodes(); //first two items
let [ code1, ,code3 ] = newCodes(); //skip middle item, get first & last
let [ ,, code3 ] = newCodes(); //skip first two items, get last
let [ code1, ...rest ] = newCodes(); //first item, and others as an array

Vale la pena notare che ...restdovrebbe sempre essere alla fine in quanto non ha senso distruggere nulla dopo che tutto il resto è aggregato rest.

Spero che questo aggiunga un po 'di valore a questa domanda :)


5

Puoi anche fare:

function a(){
  var d=2;
  var c=3;
  var f=4;
  return {d:d,c:c,f:f}
}

const {d,c,f} = a()

5

Un modo molto comune per restituire più valori in JavaScript è usare un oggetto letterali , quindi qualcosa di simile:

const myFunction = () => {
  const firstName = "Alireza", 
        familyName = "Dezfoolian",
        age = 35;
  return { firstName, familyName, age};
}

e ottieni valori come questo:

myFunction().firstName; //Alireza
myFunction().familyName; //Dezfoolian
myFunction().age; //age

o anche un modo più breve:

const {firstName, familyName, age} = myFunction();

e ottenerli singolarmente come:

firstName; //Alireza
familyName; //Dezfoolian
age; //35

4

Puoi usare "Oggetto"

function newCodes(){
    var obj= new Object();
    obj.dCodes = fg.codecsCodes.rs;
    obj.dCodes2 = fg.codecsCodes2.rs;

    return obj;
}

1
Questa è la strada da percorrere per IE. Uso successivo come: let obj = newCodes (); allarme (obj.dCodes);
Asen Kasimov,

3

Va tutto bene. returnelabora logicamente da sinistra a destra e restituisce l'ultimo valore.

function foo(){
    return 1,2,3;
}

>> foo()
>> 3

1
la ,è un operatore e può essere utilizzato in qualsiasi espressione. Non c'è niente di speciale returnqui.
Gman,

3

Suggerirei di utilizzare l'ultimo compito di destrutturazione (ma assicurati che sia supportato nel tuo ambiente )

var newCodes = function () {
    var dCodes = fg.codecsCodes.rs;
    var dCodes2 = fg.codecsCodes2.rs;
    return {firstCodes: dCodes, secondCodes: dCodes2};
};
var {firstCodes, secondCodes} = newCodes()

2

Conosco due modi per farlo: 1. Return as Array 2. Return as Object

Ecco un esempio che ho trovato:

<script>
// Defining function
function divideNumbers(dividend, divisor){
    var quotient = dividend / divisor;
    var arr = [dividend, divisor, quotient];
    return arr;
}

// Store returned value in a variable
var all = divideNumbers(10, 2);

// Displaying individual values
alert(all[0]); // 0utputs: 10
alert(all[1]); // 0utputs: 2
alert(all[2]); // 0utputs: 5
</script>



<script>
// Defining function
function divideNumbers(dividend, divisor){
    var quotient = dividend / divisor;
    var obj = {
        dividend: dividend,
        divisor: divisor,
        quotient: quotient
    };
    return obj;
}

// Store returned value in a variable
var all = divideNumbers(10, 2);

// Displaying individual values
alert(all.dividend); // 0utputs: 10
alert(all.divisor); // 0utputs: 2
alert(all.quotient); // 0utputs: 5
</script>

1

Pochi giorni fa avevo lo stesso requisito di ottenere più valori di ritorno da una funzione che avevo creato.

Da molti valori di ritorno, ne avevo bisogno per restituire solo un valore specifico per una determinata condizione e quindi un altro valore di ritorno corrispondente ad altre condizioni.


Ecco l'esempio di come l'ho fatto:

Funzione:

function myTodayDate(){
    var today = new Date();
    var day = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];
    var month = ["January","February","March","April","May","June","July","August","September","October","November","December"];
    var myTodayObj = 
    {
        myDate : today.getDate(),
        myDay : day[today.getDay()],
        myMonth : month[today.getMonth()],
        year : today.getFullYear()
    }
    return myTodayObj;
}

Come ottenere il valore restituito dall'oggetto restituito dalla funzione:

var todayDate = myTodayDate().myDate;
var todayDay = myTodayDate().myDay;
var todayMonth = myTodayDate().myMonth;
var todayYear = myTodayDate().year;

Il punto centrale di rispondere a questa domanda è condividere questo approccio per ottenere un buon formato per Date. Spero che ti abbia aiutato :)


1

Non sto aggiungendo altro qui, ma un altro modo alternativo.

 var newCodes = function() {
     var dCodes = fg.codecsCodes.rs;
     var dCodes2 = fg.codecsCodes2.rs;
     let [...val] = [dCodes,dCodes2];
     return [...val];
 };

0

Bene, non possiamo fare esattamente quello che stai provando. Ma si può fare qualcosa che potrebbe succedere sotto.

function multiReturnValues(){
    return {x:10,y:20};
}

Quindi quando si chiama il metodo

const {x,y} = multiReturnValues();

console.log(x) ---> 10
console.log(y) ---> 20
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.