Zwracać wiele wartości w JavaScript?

844

Próbuję zwrócić dwie wartości w JavaScript . czy to możliwe?

var newCodes = function() {  
    var dCodes = fg.codecsCodes.rs;
    var dCodes2 = fg.codecsCodes2.rs;
    return dCodes, dCodes2;
};
Asim Zaidi
źródło
możesz to rozwiązać za pomocą oddzwaniania, jeśli chcesz to zrobić, zobacz moją odpowiedź. Ludzie zapominają, że możesz łatwo „zwrócić wiele wartości” za pomocą JS, używając krotek lub nawet: wywołań zwrotnych!
Alexander Mills,
16
Odpowiedzi są nieaktualne. To jest teraz możliwe. 2ality.com/2014/06/es6-multiple-return-values.html
Erel Segal-Halevi
3
Technicznie nadal zwracasz pojedynczy obiekt / tablicę, to tylko dekonstrukcja, która jest prostsza w ES6.
Andrea Bergonzo,

Odpowiedzi:

1295

Nie, ale możesz zwrócić tablicę zawierającą twoje wartości:

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

Następnie możesz uzyskać do nich dostęp w następujący sposób:

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

Dzięki najnowszej składni ECMAScript 6 * możesz także bardziej intuicyjnie rozkładać wartość zwracaną:

const [first, second] = getValues();

Jeśli chcesz umieścić „etykiety” na każdej ze zwracanych wartości (łatwiejsze do utrzymania), możesz zwrócić obiekt:

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

I aby uzyskać do nich dostęp:

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

Lub ze składnią ES6:

const {first, second} = getValues();

* Zobacz tę tabelę w celu uzyskania zgodności przeglądarki. Zasadniczo wszystkie współczesne przeglądarki oprócz IE obsługują tę składnię, ale można skompilować kod ES6 do JavaScript kompatybilnego z IE podczas kompilacji za pomocą narzędzi takich jak Babel .

Sasha Chedygov
źródło
151
Lub możesz zwrócić obiekt: return {dCodes : dCodes, dCodes2 : dCodes2};aby ułatwić odniesienie.
Intelekshual
10
możesz nawet zwrócić obiekt {: dCodes: dCodes, dCodes2: dCodes2} funkcjonalnie tak samo, ale kiedy odwołujesz się do zwracanego obiektu, masz nieco bardziej czytelny kod jako obj.dCodes i obj.dCodes2 vs obj [0] i obj [1 ]
Jonathan S.
1
@alexela Pewnie, możesz po prostu użyć var ​​dCodes = newCodes (). dCodes; var dCodes2 = newCodes (). dCodes2 Jednak wywołasz funkcję dwukrotnie, co może być marnowaniem zasobów, jeśli jest złożona.
Vadim Kirilchuk
12
@VadimKirilchuk Nie trzeba dzwonić dwa razy z zadaniem restrukturyzacji - np. const { dCodes, dCodes2 } = newCodes();
Taylor Edmiston
7
jak mówiły inne odpowiedzi (i sugerowane komentarze), ES6 oferuje tutaj kilka opcji. 3 dokładniej: (1) skrócona właściwość obiektu return {dCodes, dCodes2} działa tak samo jak wspomniany @Intelekshual i (2) używając tej samej funkcji można po prostu uzyskać do nich dostęp za pomocą tablic destrukcyjnych [dCodes, dCodes2] = newCodes()lub (3) obiektów ({dCodes, dCodes2} = newCodes())(nie trzeba tam używać deklaracji @Taylor , choć varbardziej pasuje do obecnego przykładu Sashy).
cregox
241

Możesz to zrobić od wersji Javascript 1.7, używając „przypisań do restrukturyzacji” . Zauważ, że nie są one dostępne w starszych wersjach Javascript (co oznacza - ani w ECMAScript 3., ani 5. edycji).

Umożliwia przypisanie do 1+ zmiennych jednocześnie:

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

// or

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

Możesz także użyć funkcji destrukcji obiektu w połączeniu ze skrótem wartości właściwości, aby nazwać zwracane wartości w obiekcie i wybrać te, które chcesz:

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

A tak przy okazji, nie dajcie się zwieść faktowi, że ECMAScript pozwala na to return 1, 2, .... To, co się naprawdę dzieje, nie jest tym, co mogłoby się wydawać. Wyrażenie w instrukcji return - 1, 2, 3- to nic innego operatora przecinek stosowane do literałów liczbowych ( 1, 2, i 3) sekwencyjnie, co ostatecznie ocenia do wartości jego ostatniej wypowiedzi - 3. Dlatego return 1, 2, 3jest funkcjonalnie identyczny z niczym innym jak return 3.

return 1, 2, 3;
// becomes
return 2, 3;
// becomes
return 3;
kangax
źródło
1
Dziwna i interesująca rzecz w ostatnim przykładzie: za function foo(){return 1,2,3;}zrobienie console.log([].push(foo()))wydruków 1.
Meredith,
@ AurélienOoms Zdałem sobie sprawę później. Dzięki
Meredith,
1
dlaczego var [x, y] = [1, 2]; x; // 1 rok; // 2 to nie działa w chrome? zgłosić błąd; ReferenceError: Niepoprawna lewa strona w przypisaniu
Naveen Agarwal
1
Chrome v49 został wydany tydzień temu, obsługując „zadania restrukturyzacyjne” od razu po wyjęciu z pudełka.
Eugene Kulabuhov,
1
To powinna być zaakceptowana odpowiedź - nowa destrukcja to świetny sposób na zrobienie tego.
Jez
68

Zwróć dosłownie obiekt

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
źródło
@SeanKinsey Podoba mi się to rozwiązanie. Może mi się przydać. Jedno pytanie, czy powinna być potrzebna funkcja w zwrocie, czy każda instancja wyniku ( wynik1 .. wynikN ) otrzyma swoją własną kopię funkcji, czy też byłoby użycie kodu funkcji? (Nie wiem, jak mogłem to przetestować.) TIA.
Karl
44

Od ES6 możesz to zrobić

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

let {dCodes, dCodes2} = newCodes()

Zwracane wyrażenie {dCodes, dCodes2}jest skrótem wartości właściwości i jest równoważne z tym {dCodes: dCodes, dCodes2: dCodes2}.

To przypisanie w ostatnim wierszu nazywa się przypisaniem niszczenia obiektów . Wyodrębnia wartość właściwości obiektu i przypisuje ją do zmiennej o tej samej nazwie. Jeśli chcesz przypisać zwracane wartości do zmiennych o różnych nazwach, możesz to zrobić w ten sposóblet {dCodes: x, dCodes2: y} = newCodes()

Peracek
źródło
27

Ecmascript 6 zawiera „przypisania do restrukturyzacji” (jak wspomniano w Kangax), więc we wszystkich przeglądarkach (nie tylko Firefox) będziesz w stanie przechwycić tablicę wartości bez konieczności tworzenia tablicy nazwanej lub obiektu wyłącznie w celu ich przechwycenia.

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

Możesz to wypróbować już w Firefoksie!

użytkownik3015682
źródło
24

Inną wartą wspomnienia nowo wprowadzoną składnią (ES6) jest użycie skrótu tworzenia obiektu oprócz niszczenia przypisania.

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

Ta składnia może być wypełniana przez babel lub inny wypełniacz js dla starszych przeglądarek, ale na szczęście teraz działa natywnie z najnowszymi wersjami Chrome i Firefox.

Ale ponieważ tworzenie nowego obiektu wiąże się z alokacją pamięci (i ewentualnym ładowaniem gc), nie oczekuj od niej dużej wydajności. JavaScript i tak nie jest najlepszym językiem do tworzenia wysoce optymalnych rzeczy, ale jeśli jest to potrzebne, możesz rozważyć umieszczenie wyniku na otaczającym obiekcie lub takich technikach, które są zwykle częstymi sztuczkami związanymi z wydajnością między JavaScript, Java i innymi językami.

Ebrahim Byagowi
źródło
To jeszcze nie działa na IE lub Edge, chciałem tylko zauważyć.
user1133275
Używałem tego dość dużo ... jest szybsze / płynniejsze korzystanie z tablicy i unikanie konstruowania obiektu, jeśli to możliwe, jak pokazuje @ user3015682.
dkloke,
18

Najlepszym sposobem na to jest

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

Następnie użyj

a().f

zwrot 4

w ES6 możesz użyć tego kodu

function a(){
      var d=2;
      var c=3;
      var f=4;
      return {d,c,f}
}
Behnam Mohammadi
źródło
Następnie uruchomić ponownie funkcję dla każdej zmiennej? To nie jest najlepsze podejście.
Elia Iliashenko
ta funkcja zwraca wiele wartości, być może nie jest to najlepsze podejście.
Behnam Mohammadi
Za każdym razem, gdy interpreter napotyka (), ponownie uruchamia funkcję. Zatem var f = a (). F; var c = a (). c; var d = a (). d; uruchomi () trzy razy, co jest podatne na utratę wydajności. Lepszym rozwiązaniem byłoby var result = a (); var f = wynik. f; itp.
Elia Iliashenko
1
ok dla lepszej wydajności, możesz zachować wartość zmiennej i użyć jej, na przykład var result = a (); i użyj wartości wynik.d lub wynik.c i wynik.f, więc tylko raz uruchom funkcję ().
Behnam Mohammadi
9

Oprócz zwracania tablicy lub obiektu, jak zalecają inni, możesz również użyć funkcji kolekcjonerskiej (podobnej do tej znalezionej w The Little Schemer ):

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

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

Zrobiłem test jsperf, aby zobaczyć, która z trzech metod jest szybsza. Tablica jest najszybsza, a kolektor jest najwolniejszy.

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

Zelenova
źródło
Zazwyczaj collectornazywa się to, continuationa technika nazywa się CPS
ceving
7

W JS możemy łatwo zwrócić krotkę z tablicą lub obiektem, ale nie zapomnij! => JS jest callbackjęzykiem zorientowanym i istnieje tutaj mały sekret „zwracania wielu wartości”, o których nikt jeszcze nie wspomniał, spróbuj tego:

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

staje się

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

:)

bam! To po prostu inny sposób rozwiązania problemu.

Alexander Mills
źródło
6

Dodanie brakujących ważnych części, aby uczynić to pytanie kompletnym zasobem, ponieważ pojawia się w wynikach wyszukiwania.

Niszczenie obiektów

W przypadku destrukcji obiektów niekoniecznie musisz używać tej samej wartości klucza co nazwa zmiennej, możesz przypisać inną nazwę zmiennej, definiując ją jak poniżej:

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

Niszczenie tablic

W rozkładzie tablic możesz pominąć niepotrzebne wartości.

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

Warto zauważyć, że ...restzawsze powinno to być na końcu, ponieważ nie ma sensu niszczyć niczego po agregacji wszystkiego innego rest.

Mam nadzieję, że doda to pewnej wartości temu pytaniu :)

Nimeshka Srimal
źródło
5

Możesz także:

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
źródło
5

Bardzo częstym sposobem zwracania wielu wartości w javascript jest użycie literałów obiektowych , więc coś takiego:

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

i uzyskaj takie wartości:

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

lub nawet w skrócie:

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

i zdobądź je indywidualnie:

firstName; //Alireza
familyName; //Dezfoolian
age; //35
Alireza
źródło
4

Możesz użyć „Object”

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

    return obj;
}
sebu
źródło
1
To jest droga do IE. Później użyj: let obj = newCodes (); alert (obj.dCodes);
Asen Kasimov
3

Wszystko w porządku. returnlogicznie przetwarza od lewej do prawej i zwraca ostatnią wartość.

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

>> foo()
>> 3
Artemii
źródło
1
,jest operatora i mogą być stosowane w dowolnym ekspresji. Nie ma w tym nic specjalnego return.
gman
2

Znam dwa sposoby, aby to zrobić: 1. Wróć jako tablicę 2. Wróć jako obiekt

Oto przykład, który znalazłem:

<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
źródło
1

Kilka dni temu miałem podobny wymóg uzyskania wielu zwracanych wartości z funkcji, którą utworzyłem.

Z wielu zwracanych wartości potrzebowałem, aby zwracała tylko określoną wartość dla danego warunku, a następnie inną wartość zwracaną odpowiadającą innemu warunkowi.


Oto przykład tego, jak to zrobiłem:

Funkcjonować:

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

Pobieranie wymaganej wartości zwracanej z obiektu zwróconego przez funkcję:

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

Istotą odpowiedzi na to pytanie jest podzielenie się podejściem polegającym na otrzymaniu Data w dobrym formacie. Mam nadzieję, że to ci pomogło :)

krupesh Anadkat
źródło
1

Nie dodam tu nic nowego, tylko inny alternatywny sposób.

 var newCodes = function() {
     var dCodes = fg.codecsCodes.rs;
     var dCodes2 = fg.codecsCodes2.rs;
     let [...val] = [dCodes,dCodes2];
     return [...val];
 };
kumar
źródło
0

Cóż, nie możemy dokładnie zrobić tego, co próbujesz. Ale można zrobić coś poniżej.

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

Następnie podczas wywoływania metody

const {x,y} = multiReturnValues();

console.log(x) ---> 10
console.log(y) ---> 20
Anjana
źródło