¿Devolver múltiples valores en JavaScript?

847

Estoy tratando de devolver dos valores en JavaScript . es posible?

var newCodes = function() {  
    var dCodes = fg.codecsCodes.rs;
    var dCodes2 = fg.codecsCodes2.rs;
    return dCodes, dCodes2;
};
Asim Zaidi
fuente
puede resolver esto utilizando devoluciones de llamada, si está dispuesto a hacerlo, vea mi respuesta. La gente olvida que puedes "devolver múltiples valores" fácilmente con JS, usando tuplas o incluso: ¡devoluciones de llamada!
Alexander Mills
16
Las respuestas están desactualizadas. Ahora es posible 2ality.com/2014/06/es6-multiple-return-values.html
Erel Segal-Halevi
3
Técnicamente, todavía está devolviendo un solo objeto / matriz, es solo la deconstrucción que es más simple en ES6.
Andrea Bergonzo

Respuestas:

1301

No, pero podría devolver una matriz que contenga sus valores:

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

Entonces puedes acceder a ellos de esta manera:

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

Con la última sintaxis ECMAScript 6 *, también puede desestructurar el valor de retorno de forma más intuitiva:

const [first, second] = getValues();

Si desea poner "etiquetas" en cada uno de los valores devueltos (más fácil de mantener), puede devolver un objeto:

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

Y para acceder a ellos:

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

O con la sintaxis de ES6:

const {first, second} = getValues();

* Consulte esta tabla para ver la compatibilidad del navegador. Básicamente, todos los navegadores modernos aparte de IE admiten esta sintaxis, pero puede compilar el código ES6 a JavaScript compatible con IE en el momento de la compilación con herramientas como Babel .

Sasha Chedygov
fuente
151
O puede devolver un objeto: return {dCodes : dCodes, dCodes2 : dCodes2};para que sea más fácil hacer referencia.
Intelekshual
10
incluso puede devolver un objeto {: dCodes: dCodes, dCodes2: dCodes2} funcionalmente el mismo pero cuando hace referencia a su objeto devuelto tiene un código un poco más legible como obj.dCodes y obj.dCodes2 vs obj [0] y obj [1 ]
Jonathan S.
1
@alexela Claro que simplemente puede usar var dCodes = newCodes (). dCodes; var dCodes2 = newCodes (). dCodes2 Sin embargo, llamará a la función dos veces, lo que puede ser un desperdicio de recursos si es complejo.
Vadim Kirilchuk
12
@VadimKirilchuk No es necesario llamarlo dos veces con asignación de desestructuración - ej. const { dCodes, dCodes2 } = newCodes();
Taylor Edmiston
77
Como dijeron otras respuestas (y comentarios implícitos), ES6 trae algunas opciones aquí. 3 para ser exactos: (1) la taquigrafía de la propiedad del objeto return {dCodes, dCodes2} funciona igual que @Intelekshual mencionado y (2) usando la misma función, simplemente puede acceder a ellos con matrices de desestructuración [dCodes, dCodes2] = newCodes()u (3) objetos ({dCodes, dCodes2} = newCodes())(no es necesario usar una declaración allí @Taylor , aunque varsería más apropiado para el ejemplo actual de Sasha).
cregox
241

Puede hacer esto desde Javascript 1.7 en adelante usando "tareas de desestructuración" . Tenga en cuenta que estos no están disponibles en versiones anteriores de Javascript (es decir, ni con ECMAScript 3ª ni 5ª edición).

Le permite asignar a 1+ variables simultáneamente:

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

// or

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

También puede usar la desestructuración de objetos combinada con el valor de la propiedad de forma abreviada para nombrar los valores de retorno en un objeto y elegir los que desee:

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

Y, por cierto, no se deje engañar por el hecho de que ECMAScript se lo permite return 1, 2, .... Lo que realmente sucede allí no es lo que podría parecer. Una expresión en la instrucción de retorno - 1, 2, 3- no es más que un operador coma aplica a los literales numéricos ( 1, 2y 3) de manera secuencial, lo que finalmente da como resultado el valor de su última expresión - 3. Por eso return 1, 2, 3es funcionalmente idéntico a nada más que return 3.

return 1, 2, 3;
// becomes
return 2, 3;
// becomes
return 3;
kangax
fuente
1
Algo extraño e interesante sobre el último ejemplo: para function foo(){return 1,2,3;}hacer una copia console.log([].push(foo()))impresa 1.
Meredith
@ AurélienOoms me di cuenta más tarde. Gracias
Meredith
1
por qué var [x, y] = [1, 2]; X; // 1 y; // 2 esto no funciona en cromo? plantear un error; ReferenceError: lado izquierdo no válido en asignación
Naveen Agarwal
1
Chrome v49 se lanzó hace una semana y admite "tareas de desestructuración" listas para usar.
Eugene Kulabuhov
1
Esta debería ser la respuesta aceptada: la nueva desestructuración es una excelente manera de hacerlo.
Jez
68

Solo devuelve un objeto literal

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);
Sean Kinsey
fuente
@SeanKinsey Me gusta esta solución. Puede ser útil para mi. Una pregunta, debe haber una necesidad de una función en el retorno haría cada caso de resultado ( resultado1 .. resultN ) obtener su propia copia de la función o ¿habría resuse del código de función? (No sé cómo podría probar esto). TIA.
Karl
44

Desde ES6 puedes hacer esto

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

let {dCodes, dCodes2} = newCodes()

La expresión de retorno {dCodes, dCodes2}es un valor de propiedad abreviado y es equivalente a esto {dCodes: dCodes, dCodes2: dCodes2}.

Esta asignación en la última línea se llama asignación de destrucción de objetos . Extrae el valor de propiedad de un objeto y lo asigna a la variable del mismo nombre. Si desea asignar valores de retorno a variables de diferente nombre, puede hacerlo asílet {dCodes: x, dCodes2: y} = newCodes()

Peracek
fuente
27

Ecmascript 6 incluye "tareas de desestructuración" (como mencionó kangax), por lo que en todos los navegadores (no solo Firefox) podrá capturar una matriz de valores sin tener que crear una matriz u objeto con el único propósito de capturarlos.

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

¡Ya puedes probarlo en Firefox!

usuario3015682
fuente
24

Otra digna de mencionar la sintaxis recién introducida (ES6) es el uso de la taquigrafía de creación de objetos además de la asignación de destrucción.

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

Esta sintaxis se puede rellenar con babel u otro polyfiller js para navegadores antiguos, pero afortunadamente ahora funciona de forma nativa con las versiones recientes de Chrome y Firefox.

Pero como hacer un nuevo objeto, la asignación de memoria (y la eventual carga gc) están involucrados aquí, no esperes mucho rendimiento de él. De todos modos, JavaScript no es el mejor lenguaje para desarrollar cosas altamente óptimas, pero si es necesario, puede considerar colocar su resultado en un objeto circundante o en esas técnicas, que generalmente son trucos de rendimiento comunes entre JavaScript, Java y otros lenguajes.

Ebrahim Byagowi
fuente
Eso aún no funciona en IE o Edge, solo quería señalar.
usuario1133275
He estado usando esto bastante ... es más rápido / suave usar una matriz y evitar construir un objeto si es posible, como lo muestra @ user3015682.
dkloke
18

La mejor manera para esto es

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

Luego usa

a().f

retorno 4

en ES6 puedes usar este código

function a(){
      var d=2;
      var c=3;
      var f=4;
      return {d,c,f}
}
Behnam Mohammadi
fuente
Luego ejecuta la función nuevamente para cada variable? Ese no es el mejor enfoque.
Elia Iliashenko
Esta función devuelve valores múltiples, tal vez no sea el mejor enfoque.
Behnam Mohammadi
Cada vez que el intérprete se encuentra con un (), vuelve a ejecutar la función. Entonces, var f = a (). F; var c = a (). c; var d = a (). d; lanzará un () tres veces, que es propenso a la pérdida de rendimiento. El mejor enfoque sería var result = a (); var f = resultado.f; etc.
Elia Iliashenko
1
ok para un mejor rendimiento, puede mantener el valor de una variable y usarlo, por ejemplo var result = a (); y use el valor result.d o result.c y result.f, así que solo una vez ejecute una función ().
Behnam Mohammadi
9

Además de devolver una matriz o un objeto como otros han recomendado, también puede usar una función de recopilador (similar a la que se encuentra en The Little Schemer ):

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

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

Hice una prueba jsperf para ver cuál de los tres métodos es más rápido. La matriz es más rápida y el recolector es el más lento.

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

Zelenova
fuente
Por collectorlo general, se llama continuationy la técnica se llama CPS
termina
7

En JS, podemos devolver fácilmente una tupla con una matriz u objeto, ¡pero no lo olvide! => JS es un callbacklenguaje orientado, y aquí hay un pequeño secreto para "devolver múltiples valores" que nadie ha mencionado aún, intente esto:

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

se convierte

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

:)

bam! Esta es simplemente otra forma de resolver su problema.

Alexander Mills
fuente
6

Agregar las partes importantes que faltan para hacer de esta pregunta un recurso completo, ya que esto aparece en los resultados de búsqueda.

Desestructuración de objetos

En la desestructuración de objetos, no necesariamente necesita usar el mismo valor clave que su nombre de variable, puede asignar un nombre de variable diferente definiéndolo de la siguiente manera:

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

Desestructuración de matrices

En la desestructuración de matrices, puede omitir los valores que no necesita.

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 notar que ...restsiempre debe estar al final, ya que no tiene sentido destruir nada después de que todo lo demás se agregue arest .

Espero que esto agregue algo de valor a esta pregunta :)

Nimeshka Srimal
fuente
5

También puedes hacer:

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

const {d,c,f} = a()
Joris Mans
fuente
5

Una forma muy común de devolver múltiples valores en javascript es usar un objeto literal , por lo que algo como:

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

y obtener los valores como este:

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

o incluso un camino más corto:

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

y obtenerlos individualmente como:

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

Puedes usar "Objeto"

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

    return obj;
}
sebu
fuente
1
Este es el camino a seguir para IE. Uso posterior como: let obj = newCodes (); alerta (obj.dCodes);
Asen Kasimov
3

Todo esta correcto. returnprocesa lógicamente de izquierda a derecha y devuelve el último valor.

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

>> foo()
>> 3
Artemii
fuente
1
El ,es un operador y se puede utilizar en cualquier expresión. No hay nada especial returnaquí.
gman
3

Sugeriría utilizar la última asignación de desestructuración (pero asegúrese de que sea compatible con su entorno )

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

Conozco dos formas de hacer esto: 1. Volver como matriz 2. Volver como objeto

Aquí hay un ejemplo que encontré:

<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>
Kallol Medhi
fuente
1

Hace unos días tuve el requisito similar de obtener múltiples valores de retorno de una función que creé.

De muchos valores de retorno, lo necesitaba para devolver solo un valor específico para una condición dada y luego otro valor de retorno correspondiente a otra condición.


Aquí está el ejemplo de cómo hice eso:

Función:

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

Obteniendo el valor de retorno requerido del objeto devuelto por la función:

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

El objetivo de responder a esta pregunta es compartir este enfoque de obtener la fecha en buen formato. Espero que te haya ayudado :)

krupesh Anadkat
fuente
1

No agrego nada nuevo aquí, sino otra forma alternativa.

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

Bueno, no podemos hacer exactamente lo que estás intentando. Pero es probable que se pueda hacer algo a continuación.

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

Luego, al llamar al método

const {x,y} = multiReturnValues();

console.log(x) ---> 10
console.log(y) ---> 20
Anjana
fuente