Retornar vários valores em JavaScript?

846

Estou tentando retornar dois valores em JavaScript . Isso é possível?

var newCodes = function() {  
    var dCodes = fg.codecsCodes.rs;
    var dCodes2 = fg.codecsCodes2.rs;
    return dCodes, dCodes2;
};
Asim Zaidi
fonte
você pode resolver isso usando retornos de chamada; se estiver disposto a fazê-lo, veja minha resposta. As pessoas esquecem que você pode "retornar vários valores" facilmente com JS, usando tuplas ou até: retornos de chamada!
Alexander Mills
16
As respostas estão desatualizadas. Agora é possível. 2ality.com/2014/06/es6-multiple-return-values.html
Segal-Halevi
3
Tecnicamente, você ainda está retornando um único objeto / matriz, é apenas a desconstrução que é mais simples no ES6.
Andrea Bergonzo 15/04/19

Respostas:

1299

Não, mas você pode retornar uma matriz contendo seus valores:

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

Então você pode acessá-los assim:

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

Com a mais recente sintaxe do ECMAScript 6 *, você também pode desestruturar o valor de retorno de forma mais intuitiva:

const [first, second] = getValues();

Se você deseja colocar "rótulos" em cada um dos valores retornados (mais fáceis de manter), você pode retornar um objeto:

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

E para acessá-los:

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

Ou com a sintaxe do ES6:

const {first, second} = getValues();

* Consulte esta tabela para compatibilidade do navegador. Basicamente, todos os navegadores modernos, exceto o IE, oferecem suporte a essa sintaxe, mas você pode compilar o código ES6 até o JavaScript compatível com o IE no momento da criação, com ferramentas como Babel .

Sasha Chedygov
fonte
151
Ou você pode retornar um objeto: return {dCodes : dCodes, dCodes2 : dCodes2};para facilitar a referência.
Intelekshual
10
você pode até retornar um objeto {: dCodes: dCodes, dCodes2: dCodes2} funcionalmente o mesmo, mas quando você faz referência ao objeto retornado, possui um código um pouco mais legível como obj.dCodes e obj.dCodes2 vs obj [0] e obj [1 ]
Jonathan S.
1
@alexela Claro que você pode simplesmente usar var dCodes = newCodes (). dCodes; var dCodes2 = newCodes (). dCodes2 No entanto, você chamará a função duas vezes, o que pode ser um desperdício de recursos, se for complexo.
Vadim Kirilchuk 25/02
12
@VadimKirilchuk Não há necessidade de chamá-lo duas vezes com a atribuição de desestruturação - ex. const { dCodes, dCodes2 } = newCodes();
Taylor Edmiston
7
como outras respostas disseram (e os comentários implícitos), o ES6 traz algumas opções aqui. 3 para ser exato: (1) a abreviação da propriedade do objeto return {dCodes, dCodes2} funciona da mesma maneira que @Intelekshual mencionado e (2) usando a mesma função, você pode simplesmente acessá-los com matrizes de desestruturação [dCodes, dCodes2] = newCodes()ou (3) objetos ({dCodes, dCodes2} = newCodes())(não é necessário usar uma declaração no @Taylor , embora a varseja mais adequado ao exemplo atual de Sasha).
Cregox 18/03/19
241

Você pode fazer isso do Javascript 1.7 em diante usando "atribuições de desestruturação" . Observe que eles não estão disponíveis nas versões Javascript mais antigas (ou seja, nem nas edições 3 e 5 do ECMAScript).

Permite atribuir 1 ou mais variáveis ​​simultaneamente:

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

// or

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

Você também pode usar a desestruturação do objeto combinada com a abreviação do valor da propriedade para nomear os valores retornados em um objeto e selecionar os que deseja:

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

E, a propósito, não se deixe enganar pelo fato de que o ECMAScript permite return 1, 2, .... O que realmente acontece não é o que pode parecer. Uma expressão na instrução de retorno - 1, 2, 3- nada mais é que um operador vírgula aplicada a literais numéricos ( 1, 2e 3) sequencialmente, o que eventualmente avalia para o valor de sua última expressão - 3. É por isso que return 1, 2, 3é funcionalmente idêntico a nada além disso return 3.

return 1, 2, 3;
// becomes
return 2, 3;
// becomes
return 3;
kangax
fonte
1
Coisa estranha e interessante sobre o último exemplo: para function foo(){return 1,2,3;}fazer console.log([].push(foo()))impressões 1.
Meredith
@ AurélienOoms eu percebi mais tarde. Obrigado
Meredith
1
por que var [x, y] = [1, 2]; x; // 1 ano; // 2 isso não funciona no chrome? gerar um erro; ReferenceError: Lado esquerdo inválido na tarefa
Naveen Agarwal
1
O Chrome v49 foi lançado há uma semana, suportando "atribuições de desestruturação" prontas para uso.
Eugene Kulabuhov 10/03
1
Essa deve ser a resposta aceita - a nova desestruturação é uma ótima maneira de fazer isso.
Jez
68

Basta retornar um 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
fonte
@SeanKinsey Eu gosto desta solução. Pode ser útil para mim. Uma pergunta, deve haver uma necessidade de uma função no retorno seria cada instância de resultado ( result1 .. resultN ) obter sua própria cópia da função ou haveria resuse do código de função? (Não sei como pude testar isso.) TIA.
29412 Karl
44

Desde o ES6, você pode fazer isso

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

let {dCodes, dCodes2} = newCodes()

A expressão de retorno {dCodes, dCodes2}é um valor abreviado da propriedade e é equivalente a isso {dCodes: dCodes, dCodes2: dCodes2}.

Essa atribuição na última linha é chamada de atribuição de destruição de objeto . Ele extrai o valor da propriedade de um objeto e o atribui à variável de mesmo nome. Se você deseja atribuir valores de retorno a variáveis ​​de nome diferente, você pode fazê-lo assimlet {dCodes: x, dCodes2: y} = newCodes()

Peracek
fonte
27

O Ecmascript 6 inclui "atribuições de desestruturação" (como mencionado no kangax) para que em todos os navegadores (não apenas no Firefox) você possa capturar uma matriz de valores sem precisar criar uma matriz ou objeto nomeado com o único objetivo de capturá-los.

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

Você já pode experimentá-lo no Firefox!

user3015682
fonte
24

Outro destaque a ser mencionado na sintaxe recém-introduzida (ES6) é o uso da abreviação de criação de objeto, além de destruir a atribuição.

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

Essa sintaxe pode ser preenchida com babel ou outro js polyfiller para navegadores mais antigos, mas felizmente agora funciona nativamente com as versões recentes do Chrome e Firefox.

Mas, ao criar um novo objeto, a alocação de memória (e eventual carga de gc) está envolvida aqui, não espere muito desempenho dele. O JavaScript não é a melhor linguagem para o desenvolvimento de coisas altamente ideais, mas se necessário, você pode colocar o resultado em objetos ao redor ou em técnicas que geralmente são truques comuns de desempenho entre JavaScript, Java e outras linguagens.

Ebrahim Byagowi
fonte
Isso ainda não está funcionando no IE ou Edge, só queria observar.
precisa saber é o seguinte
Utilizando isso um pouco ... é mais rápido / suave usar uma matriz e evitar a construção de um objeto, se possível, como mostrado por @ user3015682.
dkloke
18

A melhor maneira para isso é

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

Então use

a().f

retorno 4

no ES6 você pode usar esse código

function a(){
      var d=2;
      var c=3;
      var f=4;
      return {d,c,f}
}
Behnam Mohammadi
fonte
Em seguida, execute a função novamente para cada variável? Essa não é a melhor abordagem.
Elia Iliashenko
esta função retorna multi valor, talvez não seja a melhor abordagem.
Behnam Mohammadi
Toda vez que o intérprete encontra um (), ele executa a função novamente. Então, var f = a (). F; var c = a (). c; var d = a (). d; lançará um () três vezes, o que é propenso a perda de desempenho. A melhor abordagem seria var result = a (); var f = resultado.f; etc.
Elia Iliashenko
1
ok para um melhor desempenho, você pode manter o valor em uma variável e usá-lo, por exemplo, var result = a (); e use o valor result.d ou result.c e result.f, portanto, ao mesmo tempo, execute uma função ().
Behnam Mohammadi
9

Além de retornar uma matriz ou um objeto, como outros recomendaram, você também pode usar uma função de coletor (semelhante à encontrada em The Little Schemer ):

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

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

Fiz um teste jsperf para ver qual dos três métodos é mais rápido. A matriz é mais rápida e o coletor é mais lento.

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

Zelenova
fonte
Normalmente collectoré chamado continuatione a técnica é chamada CPS
iniciando
7

Em JS, podemos facilmente retornar uma tupla com uma matriz ou objeto, mas não esqueça! => JS é uma callbacklinguagem orientada, e há um pequeno segredo aqui para "retornar vários valores" que ninguém ainda mencionou, tente o seguinte:

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

torna-se

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

:)

bam! Esta é simplesmente outra maneira de resolver seu problema.

Alexander Mills
fonte
6

Adicionando as partes importantes que faltam para tornar essa pergunta um recurso completo, pois isso aparece nos resultados da pesquisa.

Destruição de Objetos

Na destruição de objeto, você não precisa necessariamente usar o mesmo valor da chave que o nome da sua variável, pode atribuir um nome de variável diferente, definindo-o como abaixo:

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

Reestruturação de matriz

Na desestruturação da matriz, você pode pular os valores que não precisa.

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 notar que ...restsempre deve estar no final, pois não faz sentido destruir nada depois que todo o resto é agregado arest .

Espero que isso agregue algum valor a essa pergunta :)

Nimeshka Srimal
fonte
5

Você também pode fazer:

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
fonte
5

Uma maneira muito comum de retornar vários valores em javascript é usar um literal de objeto , algo como:

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

e obtenha os valores assim:

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

ou até uma maneira mais curta:

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

e obtenha-os individualmente como:

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

Você pode usar "Objeto"

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

    return obj;
}
sebu
fonte
1
Este é o caminho a seguir para o IE. Posteriormente use como: let obj = newCodes (); alerta (obj.dCodes);
Asen Kasimov
3

Tudo está correto. returnprocessa logicamente da esquerda para a direita e retorna o último valor.

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

>> foo()
>> 3
Artemii
fonte
1
o ,é um operador e pode ser usado em qualquer expressão. Não há nada de especial returnaqui.
gman
3

Sugiro usar a última tarefa de desestruturação (mas verifique se ela é suportada em seu ambiente )

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

Conheço duas maneiras de fazer isso: 1. Retornar como matriz 2. Retornar como objeto

Aqui está um exemplo que eu encontrei:

<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
fonte
1

Poucos dias atrás, eu tinha o requisito semelhante de obter vários valores de retorno de uma função que eu criei.

De muitos valores de retorno, eu precisava que ele retornasse apenas um valor específico para uma determinada condição e, em seguida, outro valor de retorno correspondente a outra condição.


Aqui está o exemplo de como eu fiz isso:

Função:

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

Obtendo o valor de retorno necessário do objeto retornado pela função:

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

O ponto principal de responder a essa pergunta é compartilhar essa abordagem de obter o Date em bom formato. Espero que tenha ajudado :)

krupesh Anadkat
fonte
1

Não estou acrescentando nada de novo aqui, mas de outra maneira alternativa.

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

Bem, não podemos exatamente fazer o que você está tentando. Mas algo provável abaixo pode ser feito.

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

Então, ao chamar o método

const {x,y} = multiReturnValues();

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