JavaScript'te birden fazla değer mi döndürülecek?


846

JavaScript'te iki değer döndürmeye çalışıyorum . Mümkün mü?

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

geri aramaları kullanarak bunu çözebilirsiniz, eğer bunu yapmak istiyorsanız, cevabımı görün. İnsanlar, tuples veya hatta: geri çağrılar kullanarak JS ile kolayca "birden fazla değer döndürebileceğinizi" unutuyorlar.
Alexander Mills

16
Cevaplar güncel değil. Artık mümkün. 2ality.com/2014/06/es6-multiple-return-values.html
Erel Segal-Halevi

3
Teknik olarak hala tek bir nesne / dizi döndürüyorsunuz, sadece ES6'da daha basit olan yapısöküm.
Andrea Bergonzo

Yanıtlar:


1298

Hayır, ancak değerlerinizi içeren bir dizi döndürebilirsiniz:

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

Sonra onlara şu şekilde erişebilirsiniz:

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

En son ECMAScript 6 sözdizimi * ile, dönüş değerini daha sezgisel olarak da yapılandırabilirsiniz:

const [first, second] = getValues();

Döndürülen değerlerin her birine (bakımı daha kolay) "etiketler" koymak istiyorsanız, bir nesneyi döndürebilirsiniz:

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

Ve onlara erişmek için:

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

Veya ES6 sözdizimi ile:

const {first, second} = getValues();

* Tarayıcı uyumluluğu için bu tabloya bakın . Temel olarak, IE dışındaki tüm modern tarayıcılar bu sözdizimini destekler, ancak ES6 kodunu derleme sırasında Babel gibi araçlarla IE uyumlu JavaScript'e derleyebilirsiniz .


151
Veya bir nesneyi döndürebilirsiniz: return {dCodes : dCodes, dCodes2 : dCodes2};referans vermeyi kolaylaştırmak için.
Intelekshual

10
bir nesneyi bile {: dCodes: dCodes, dCodes2: dCodes2} işleviyle aynı şekilde döndürebilirsiniz, ancak döndürülen nesneye başvurduğunuzda obj.dCodes ve obj.dCodes2 vs obj [0] ve obj [1 gibi daha okunabilir bir koda sahipsiniz. ]
Jonathan S.

1
@alexela Elbette var dCodes = newCodes (). dCodes; dCodes2 = newCodes (). dCodes2 Ancak, işlevi iki kez çağıracaksınız; bu, karmaşıksa kaynak israfı olabilir.
Vadim Kirilchuk

12
@VadimKirilchuk Yıkıcı atama ile iki kez demeye gerek yok - ör. const { dCodes, dCodes2 } = newCodes();
Taylor Edmiston

7
diğer cevapların söylediği gibi (ve ima edilen yorumlar), ES6 burada birkaç seçenek getiriyor. 3 tam olarak: (1) nesne özelliği stenografi return {dCodes, dCodes2} sadece @Intelekshual ile aynı çalışır ve (2) aynı işlevi kullanarak sadece yıkıcı diziler [dCodes, dCodes2] = newCodes()veya (3) nesnelerle onlara erişebilirsiniz ({dCodes, dCodes2} = newCodes())(orada bir bildirim kullanmaya gerek yok @Taylor olsa da var, şu anki Sasha'nın örneği için daha uygun olurdu).
cregox

241

Bunu "yıkıcı atamalar" kullanarak Javascript 1.7'den itibaren yapabilirsiniz . Bunların eski Javascript sürümlerinde mevcut olmadığını unutmayın (yani - ECMAScript 3. veya 5. sürümlerde).

Aynı anda 1+ değişkene atamanıza izin verir:

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

// or

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

Ayrıca , bir nesnedeki dönüş değerlerini adlandırmak ve istediklerinizi seçmek için özellik değeri ile birlikte nesne yok etme özelliğini de kullanabilirsiniz :

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

Ve bu arada, ECMAScript'in size izin verdiği gerçeği aldanmayın return 1, 2, .... Gerçekten olan şey, göründüğü gibi değil. Dönüş açıklamada bir ifade - 1, 2, 3- şey değildir ama bir virgül operatörü (sayısal değişmezleri uygulanan 1, 2ve 3en sonunda son ifadenin değeri değerlendiren hangi) sırayla - 3. Bu yüzden return 1, 2, 3işlevsel olarak başka bir şeyle aynı değildir return 3.

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

1
Son örnekle ilgili garip ve ilginç bir şey: bir baskı function foo(){return 1,2,3;}yapmak için console.log([].push(foo()))1.
Meredith

@ AurélienOoms Daha sonra farkettim. Teşekkürler
Meredith

1
neden var [x, y] = [1, 2]; x; // 1 y; // 2 bu kromda çalışmıyor? hata yapmak; ReferenceError: Görevde geçersiz sol taraf
Naveen Agarwal

1
Chrome v49 bir hafta önce kullanıma hazır "yıkım atamaları" nı destekledi.
Eugene Kulabuhov

1
Kabul edilen cevap bu olmalıdır - yeni yıkım bunu yapmanın harika bir yoludur.
Jez

68

Sadece bir nesne değişmezini döndürün

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 Bu çözümü beğendim. Benim için yararlı olabilir. Bir soru, karşılığında bir işlev için bir ihtiyaç olması gerektiğini olur her örneğini sonucu ( result1 .. resultN ) fonksiyonunun kendi kopyasını almak veya fonksiyon kodunun resuse olacaktı? (Bunu nasıl test edebileceğimi bilmiyorum.) TIA.
Karl

44

ES6'dan beri bunu yapabilirsiniz

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

let {dCodes, dCodes2} = newCodes()

Dönüş ifadesi {dCodes, dCodes2}olan özellik değeri stenografi ve bu eşdeğerdir {dCodes: dCodes, dCodes2: dCodes2}.

Son satırdaki bu atamaya nesne yok etme ataması denir . Bir nesnenin özellik değerini alır ve onu aynı addaki değişkene atar. Farklı addaki değişkenlere dönüş değerleri atamak isterseniz, bunu böyle yapabilirsinizlet {dCodes: x, dCodes2: y} = newCodes()


27

Ecmascript 6, "yıkıcı atamalar" içerir (kanguru olarak belirtildiği gibi), böylece tüm tarayıcılarda (yalnızca Firefox'ta değil), yalnızca yakalama amacıyla adlandırılmış bir dizi veya nesne yapmak zorunda kalmadan bir dizi değeri yakalayabilirsiniz.

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

Firefox'ta zaten deneyebilirsiniz!


24

Yeni tanıtılan (ES6) sözdiziminden bahsetmeye değer başka bir değer, tahrip edici atamaya ek olarak nesne yaratma stilini kısaca kullanmaktır.

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

Bu sözdizimi, daha eski tarayıcılar için babel veya diğer js polyfiller ile çoklu doldurulabilir, ancak neyse ki artık Chrome ve Firefox'un son sürümleriyle yerel olarak çalışmaktadır.

Ancak yeni bir nesne oluştururken, bellek ayırma (ve sonuç olarak gc yükü) burada yer alır, ondan çok fazla performans beklemeyin. JavaScript, zaten son derece optimal şeyler geliştirmek için en iyi dil değildir, ancak gerekirse, sonucunuzu çevreleyen nesneye veya JavaScript, Java ve diğer diller arasında genellikle ortak performans hileleri olan tekniklere koymayı düşünebilirsiniz.


Bu henüz IE veya Edge üzerinde çalışmıyor, sadece not etmek istedim.
user1133275

Bunu biraz kullanıyorum ... bir dizi kullanmak ve @ user3015682 tarafından gösterildiği gibi mümkünse bir nesne oluşturmaktan kaçınmak daha hızlı / pürüzsüz.
dkloke

18

Bunun için en iyi yol

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

Sonra kullan

a().f

dönüş 4

ES6'da bu kodu kullanabilirsiniz

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

Sonra her değişken için fonksiyon tekrar çalıştırılsın mı? Bu en iyi yaklaşım değil.
Elia Iliashenko

Bu işlev çoklu değer döndürür, belki de en iyi yaklaşım değildir.
Behnam Mohammadi

Yorumlayıcı bir () ile her karşılaştığında işlevi tekrar çalıştırır. Böylece, var f = a (). F; var c = a (). c; var d = a () d; performans kaybına eğilimli üç kez bir () başlatacaktır. Daha iyi yaklaşım var sonuç = a (); var f = sonuç. f; vb.
Elia Iliashenko

1
daha iyi performans için, bir değişkenin değerini koruyabilir ve kullanabilirsiniz, örneğin var sonuç = a (); ve sonuç.d veya sonuç.c ve sonuç.f değerlerini kullanın, böylece bir kerede bir () işlevini çalıştırın.
Behnam Mohammadi

9

Bir diziyi veya nesneyi başkalarının önerdiği gibi döndürmekten başka, bir toplayıcı işlevi de kullanabilirsiniz ( Küçük Schemer'de bulunana benzer ):

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

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

Üç yöntemden hangisinin daha hızlı olduğunu görmek için bir jsperf testi yaptım. Dizi en hızlı ve toplayıcı en yavaştır.

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


Tipik collectorolarak çağrılır continuationve tekniğe CPS
ceving

7

JS'de, bir diziyi veya nesneyle kolayca bir tuple döndürebiliriz, ancak unutmayın! => JS callbackyönlendirilmiş bir dildir ve burada henüz kimsenin bahsetmediği "birden çok değer döndürmek" için küçük bir sır vardır, şunu deneyin:

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

olur

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

:)

bam! Bu sadece probleminizi çözmenin başka bir yoludur.


6

Bu soruyu eksiksiz bir kaynak haline getirmek için eksik önemli bölümleri eklemek, çünkü bu arama sonuçlarında ortaya çıkıyor.

Nesne Yıkımı

Nesne yok etme işleminde, değişken adınızla aynı anahtar değerini kullanmanız gerekmez, aşağıdaki gibi tanımlayarak farklı bir değişken adı atayabilirsiniz:

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

Dizi Yıkım

Dizi yok etme işleminde ihtiyacınız olmayan değerleri atlayabilirsiniz.

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

Diğer ...resther şey bir araya getirildikten sonra hiçbir şeyi yok etmek mantıklı olmadığından , her zaman sonunda olması gerektiğini fark etmek gerekir rest.

Umarım bu soruya değer katar :)


5

Ayrıca şunları da yapabilirsiniz:

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

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

5

Javascript içinde birden çok değer döndürmenin çok yaygın bir yolu, bir nesne değişmezleri kullanmaktır , bu nedenle:

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

ve bunun gibi değerleri alın:

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

hatta daha kısa bir yol:

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

ve ayrı ayrı alın:

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

4

"Nesne" kullanabilirsiniz

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

    return obj;
}

1
IE için gitmenin yolu budur. Daha sonra şöyle kullanın: let obj = newCodes (); uyarısı (obj.dCodes);
Asen Kasimov

3

Hepsi doğru. returnmantıksal olarak soldan sağa işler ve son değeri döndürür.

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

>> foo()
>> 3

1
,bir operatör ve bir ifadede kullanılabilir. Burada özel bir şey returnyok.
gman

3

En son yıkıcı atamayı kullanmanızı öneririm (Ancak ortamınızda desteklendiğinden emin olun )

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

2

Bunu yapmanın iki yolunu biliyorum: 1. Dizi olarak dön 2. Nesne olarak dön

İşte bulduğum bir örnek:

<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

Birkaç gün önce, oluşturduğum bir işlevden birden fazla dönüş değeri alma benzer gereksinimim vardı.

Birçok dönüş değerlerinden, belirli bir koşul için yalnızca belirli bir değer ve daha sonra diğer koşula karşılık gelen diğer dönüş değeri döndürmek için gerekli.


İşte bunu nasıl yaptığını Örnek:

İşlev:

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

İşlev tarafından döndürülen nesneden Gerekli dönüş değeri alınıyor:

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

Bu soruyu yanıtlamanın asıl amacı, Date'i iyi bir biçimde elde etme yaklaşımını paylaşmaktır. Umarım sana yardımcı olmuştur :)


1

Burada yeni bir şey değil, başka bir alternatif yol.

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

0

Peki biz tam olarak ne denemek yapamaz. Ancak aşağıda muhtemel bir şey yapılabilir.

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

Sonra yöntemi çağırırken

const {x,y} = multiReturnValues();

console.log(x) ---> 10
console.log(y) ---> 20
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.