Renvoyer plusieurs valeurs en JavaScript?


847

J'essaie de renvoyer deux valeurs en JavaScript . Est-ce possible?

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

vous pouvez résoudre ce problème en utilisant des rappels, si vous êtes disposé à le faire, consultez ma réponse. Les gens oublient que vous pouvez "retourner plusieurs valeurs" facilement avec JS, en utilisant des tuples ou même: des rappels!
Alexander Mills

16
Les réponses sont dépassées. C'est désormais possible. 2ality.com/2014/06/es6-multiple-return-values.html
Erel Segal-Halevi

3
Techniquement, vous renvoyez toujours un seul objet / tableau, c'est juste la déconstruction qui est plus simple dans ES6.
Andrea Bergonzo

Réponses:


1302

Non, mais vous pouvez renvoyer un tableau contenant vos valeurs:

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

Ensuite, vous pouvez y accéder comme suit:

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

Avec la dernière syntaxe ECMAScript 6 *, vous pouvez également détruire la valeur de retour de manière plus intuitive:

const [first, second] = getValues();

Si vous souhaitez mettre des "labels" sur chacune des valeurs retournées (plus facile à maintenir), vous pouvez renvoyer un objet:

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

Et pour y accéder:

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

Ou avec la syntaxe ES6:

const {first, second} = getValues();

* Voir ce tableau pour la compatibilité du navigateur. Fondamentalement, tous les navigateurs modernes à part IE prennent en charge cette syntaxe, mais vous pouvez compiler le code ES6 en JavaScript compatible IE au moment de la construction avec des outils comme Babel .


151
Ou vous pouvez renvoyer un objet: return {dCodes : dCodes, dCodes2 : dCodes2};pour le rendre plus facile à référencer.
Intelekshual

10
vous pouvez même renvoyer un objet {: dCodes: dCodes, dCodes2: dCodes2} de la même manière mais lorsque vous référencez votre objet renvoyé, vous avez un code un peu plus lisible comme obj.dCodes et obj.dCodes2 vs obj [0] et obj [1 ]
Jonathan S.

1
@alexela Bien sûr, vous pouvez simplement utiliser var dCodes = newCodes (). dCodes; var dCodes2 = newCodes (). dCodes2 Cependant, vous appellerez la fonction deux fois, ce qui peut être un gaspillage de ressources si elle est complexe.
Vadim Kirilchuk

12
@VadimKirilchuk Pas besoin de l'appeler deux fois avec une affectation de déstructuration - ex. const { dCodes, dCodes2 } = newCodes();
Taylor Edmiston

7
comme l'ont dit d'autres réponses (et commentaires implicites), ES6 apporte ici quelques options. 3 pour être exact: (1) les raccourcis de propriété d'objet return {dCodes, dCodes2} fonctionnent exactement comme @Intelekshual mentionné et (2) en utilisant la même fonction, vous pouvez simplement y accéder avec des tableaux de déstructuration [dCodes, dCodes2] = newCodes()ou (3) des objets ({dCodes, dCodes2} = newCodes())(pas besoin d'utiliser une déclaration ici @Taylor , bien que a varserait plus approprié pour l'exemple actuel de Sasha).
cregox

241

Vous pouvez le faire à partir de Javascript 1.7 en utilisant des "affectations de déstructuration" . Notez que ceux-ci ne sont pas disponibles dans les anciennes versions de Javascript (ce qui signifie - ni avec ECMAScript 3e ni 5e éditions).

Il vous permet d'affecter à 1+ variables simultanément:

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

// or

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

Vous pouvez également utiliser la déstructuration d'objet combinée à un raccourci de valeur de propriété pour nommer les valeurs de retour dans un objet et sélectionner celles que vous souhaitez:

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

Et en passant, ne vous laissez pas berner par le fait que ECMAScript vous le permet return 1, 2, .... Ce qui se passe vraiment là-bas n'est pas ce qui peut sembler. Une expression dans la déclaration de retour - 1, 2, 3- n'est qu'un opérateur virgule appliqué à littéraux numériques ( 1, 2et 3) de manière séquentielle, qui évalue finalement à la valeur de sa dernière expression - 3. C'est pourquoi return 1, 2, 3est fonctionnellement identique à rien de plus return 3.

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

1
Chose étrange et intéressante sur le dernier exemple: pour un function foo(){return 1,2,3;}faire console.log([].push(foo()))imprime 1.
Meredith

@ AurélienOoms je m'en suis rendu compte plus tard. Merci
Meredith

1
pourquoi var [x, y] = [1, 2]; X; // 1 y; // 2 cela ne fonctionne pas en chrome? déclencher une erreur; ReferenceError: Côté gauche non valide en affectation
Naveen Agarwal

1
Chrome v49 a été publié il y a une semaine et prend en charge les "affectations de déstructuration" prêtes à l'emploi.
Eugene Kulabuhov

1
Cela devrait être la réponse acceptée - la nouvelle déstructuration est un excellent moyen de le faire.
Jez

68

Retourne juste un objet littéral

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 J'aime cette solution. Cela peut être utile pour moi. Une question, devrait-il y avoir un besoin d'une fonction dans le retour, chaque instance de result ( result1 .. resultN ) obtiendrait-elle sa propre copie de la fonction ou y aurait-il une réutilisation du code de fonction? (Je ne sais pas comment je pourrais tester cela.) TIA.
Karl

44

Depuis ES6, vous pouvez le faire

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

let {dCodes, dCodes2} = newCodes()

L'expression de retour {dCodes, dCodes2}est un raccourci de valeur de propriété et est équivalente à cela {dCodes: dCodes, dCodes2: dCodes2}.

Cette affectation sur la dernière ligne est appelée affectation destructrice d'objets . Il extrait la valeur de propriété d'un objet et l'affecte à une variable du même nom. Si vous souhaitez attribuer des valeurs de retour à des variables de nom différent, vous pouvez le faire comme cecilet {dCodes: x, dCodes2: y} = newCodes()


27

Ecmascript 6 inclut des "assignations de déstructuration" (comme l'a mentionné kangax), donc dans tous les navigateurs (pas seulement Firefox), vous pourrez capturer un tableau de valeurs sans avoir à créer un tableau ou un objet nommé dans le seul but de les capturer.

//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(); 

Vous pouvez déjà l'essayer dans Firefox!


24

Une autre valeur à mentionner (ES6) est une syntaxe nouvellement introduite: l'utilisation du raccourci de création d'objet en plus de la destruction de l'affectation.

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);

Cette syntaxe peut être remplie avec babel ou un autre polyfiller js pour les navigateurs plus anciens, mais heureusement, elle fonctionne désormais de manière native avec les versions récentes de Chrome et Firefox.

Mais comme créer un nouvel objet, l'allocation de mémoire (et éventuellement la charge de GC) sont impliqués ici, ne vous attendez pas à beaucoup de performances de sa part. JavaScript n'est de toute façon pas le meilleur langage pour développer des choses hautement optimales, mais si cela est nécessaire, vous pouvez envisager de mettre votre résultat sur un objet environnant ou de telles techniques qui sont généralement des astuces de performance courantes entre JavaScript, Java et d'autres langages.


Cela ne fonctionne pas encore sur IE ou Edge, je voulais juste le noter.
user1133275

J'ai utilisé cela un peu ... il est plus rapide / plus fluide d'utiliser un tableau et d'éviter de construire un objet si possible, comme indiqué par @ user3015682.
dkloke

18

Le meilleur moyen pour cela est

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

Ensuite, utilisez

a().f

retour 4

dans ES6, vous pouvez utiliser ce code

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

Ensuite, exécutez à nouveau la fonction pour chaque variable? Ce n'est pas la meilleure approche.
Elia Iliashenko du

cette fonction renvoie plusieurs valeurs, ce n'est peut-être pas la meilleure approche.
Behnam Mohammadi

Chaque fois que l'interpréteur rencontre un (), il exécute à nouveau la fonction. Donc, var f = a (). F; var c = a (). c; var d = a (). d; lancera un () trois fois, ce qui est sujet à une perte de performances. La meilleure approche serait var result = a (); var f = result.f; etc.
Elia Iliashenko

1
ok pour de meilleures performances, vous pouvez conserver la valeur d'une variable et l'utiliser, par exemple var result = a (); et utilisez la valeur result.d ou result.c et result.f, donc exécutez une fonction () en une seule fois.
Behnam Mohammadi

9

Outre le retour d'un tableau ou d'un objet comme d'autres l'ont recommandé, vous pouvez également utiliser une fonction de collecteur (similaire à celle trouvée dans The Little Schemer ):

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

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

J'ai fait un test jsperf pour voir laquelle des trois méthodes est la plus rapide. Le tableau est le plus rapide et le collecteur est le plus lent.

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


collectorEst généralement appelée continuationet la technique est appelée CPS
ceving

7

En JS, nous pouvons facilement retourner un tuple avec un tableau ou un objet, mais n'oubliez pas! => JS est un callbacklangage orienté, et il y a un petit secret ici pour "retourner plusieurs valeurs" que personne n'a encore mentionné, essayez ceci:

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

devient

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

:)

bam! C'est simplement une autre façon de résoudre votre problème.


6

Ajout des parties importantes manquantes pour faire de cette question une ressource complète, car cela apparaît dans les résultats de recherche.

Déstructuration d'objets

Dans la déstructuration d'objets, vous n'avez pas nécessairement besoin d'utiliser la même valeur de clé que le nom de votre variable, vous pouvez attribuer un nom de variable différent en le définissant comme ci-dessous:

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);

Déstructuration des baies

Dans la déstructuration de tableaux, vous pouvez ignorer les valeurs dont vous n'avez pas besoin.

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

Il convient de noter que cela ...restdevrait toujours être à la fin car cela n'a aucun sens de détruire quoi que ce soit après que tout le reste soit agrégé rest.

J'espère que cela ajoutera de la valeur à cette question :)


5

Vous pouvez également faire:

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

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

5

Une façon très courante de renvoyer plusieurs valeurs en javascript consiste à utiliser un objet littéraux , donc quelque chose comme:

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

et obtenez les valeurs comme ceci:

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

ou même d'une manière plus courte:

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

et obtenez-les individuellement comme:

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

4

Vous pouvez utiliser "Objet"

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

    return obj;
}

1
C'est la voie à suivre pour IE. Utilisation ultérieure comme: let obj = newCodes (); alerte (obj.dCodes);
Asen Kasimov

3

Tout va bien. returntraite logiquement de gauche à droite et renvoie la dernière valeur.

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

>> foo()
>> 3

1
le ,est un opérateur et peut être utilisé dans toute expression. Il n'y a rien de spécial returnici.
gman


2

Je connais deux façons de procéder: 1. Retour en tant que tableau 2. Retour en tant qu'objet

Voici un exemple que j'ai trouvé:

<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

Il y a quelques jours, j'avais la même exigence d'obtenir plusieurs valeurs de retour d'une fonction que j'avais créée.

De nombreuses valeurs de retour, j'en avais besoin pour renvoyer uniquement une valeur spécifique pour une condition donnée, puis une autre valeur de retour correspondant à une autre condition.


Voici l'exemple de la façon dont je l'ai fait:

Une fonction:

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;
}

Obtention de la valeur de retour requise de l'objet renvoyé par la fonction:

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

L'intérêt de répondre à cette question est de partager cette approche pour obtenir Date dans un bon format. J'espère que cela vous a aidé :)


1

Je n'ajoute rien de nouveau ici, mais une autre manière alternative.

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

0

Eh bien, nous ne pouvons pas exactement faire ce que vous essayez. Mais quelque chose de probable ci-dessous peut être fait.

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

Puis lors de l'appel de la méthode

const {x,y} = multiReturnValues();

console.log(x) ---> 10
console.log(y) ---> 20
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.