คืนค่าหลายค่าใน JavaScript หรือไม่


845

ฉันพยายามที่จะกลับมาสองค่าในJavaScript เป็นไปได้ไหม

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

คุณสามารถแก้ปัญหานี้ได้โดยใช้การโทรกลับถ้าคุณยินดีที่จะทำเช่นนั้นดูคำตอบของฉัน ผู้คนลืมว่าคุณสามารถ "คืนค่าหลาย ๆ ค่า" ได้อย่างง่ายดายด้วย JS โดยใช้สิ่งอันดับหรือแม้กระทั่ง: โทรกลับ!
Alexander Mills

16
คำตอบนั้นล้าสมัยแล้ว มันเป็นไปได้แล้ว 2ality.com/2014/06/es6-multiple-return-values.html
Erel Segal-Halevi

3
ในทางเทคนิคคุณยังคงส่งคืนวัตถุ / อาร์เรย์เดียวมันเป็นเพียงโครงสร้างที่ง่ายกว่าใน ES6
Andrea Bergonzo

คำตอบ:


1296

ไม่ แต่คุณสามารถส่งคืนอาร์เรย์ที่มีค่าของคุณได้:

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

จากนั้นคุณสามารถเข้าถึงได้โดย:

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

ด้วยไวยากรณ์ ECMAScript 6ล่าสุด* คุณสามารถปรับโครงสร้างค่าส่งคืนได้อย่างง่ายดายยิ่งขึ้น:

const [first, second] = getValues();

หากคุณต้องการใส่ "ป้ายกำกับ" ในแต่ละค่าที่ส่งคืน (ง่ายต่อการบำรุงรักษา) คุณสามารถส่งคืนวัตถุ:

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

และเพื่อเข้าถึงพวกเขา:

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

หรือด้วยไวยากรณ์ ES6:

const {first, second} = getValues();

* ดูตารางนี้สำหรับความเข้ากันได้ของเบราว์เซอร์ โดยทั่วไปเบราว์เซอร์ที่ทันสมัยนอกเหนือจาก IE สนับสนุนรูปแบบนี้ แต่คุณสามารถรวบรวมรหัส ES6 ลงไปที่ IE รองรับ JavaScript เวลาที่สร้างด้วยเครื่องมือเช่นบาเบล


151
หรือคุณสามารถส่งคืนวัตถุ: return {dCodes : dCodes, dCodes2 : dCodes2};เพื่อให้ง่ายต่อการอ้างอิง
Intelekshual

10
คุณอาจส่งคืนวัตถุ {: dCodes: dCodes, dCodes2: dCodes2} ทำหน้าที่เหมือนกัน แต่เมื่อคุณอ้างอิงวัตถุที่ส่งคืนของคุณคุณจะมีโค้ดที่อ่านง่ายขึ้นอีกเล็กน้อยเช่น obj.dCodes และ obj.dCodes2 vs obj [0] และ obj [1] ]
Jonathan S.

1
@alexela แน่ใจว่าคุณสามารถใช้ var dCodes = newCodes () ได้ dCodes; var dCodes2 = newCodes (). dCodes2 อย่างไรก็ตามคุณจะเรียกใช้ฟังก์ชันสองครั้งซึ่งอาจเป็นการสิ้นเปลืองทรัพยากรหากมีความซับซ้อน
Vadim Kirilchuk

12
@VadimKirilchuk ไม่จำเป็นต้องเรียกมันสองครั้งด้วยการมอบหมายการทำลายล้าง - เช่น const { dCodes, dCodes2 } = newCodes();
เทย์เลอร์เอ็ดมิสตัน

7
ดังคำตอบอื่น ๆ ที่กล่าวไว้ (และความคิดเห็นโดยนัย) ES6 นำเสนอตัวเลือกไม่กี่ที่นี่ 3 ที่จะแน่นอน: (1) การย่อคุณสมบัติของวัตถุ return {dCodes, dCodes2}ทำงานเหมือนกับ @Intelekshual ที่กล่าวถึงและ (2) โดยใช้ฟังก์ชั่นเดียวกับที่คุณสามารถเข้าถึงได้ด้วยอาร์เรย์ที่ทำลาย[dCodes, dCodes2] = newCodes()หรือวัตถุ({dCodes, dCodes2} = newCodes())( 3) (ไม่จำเป็นต้องใช้การประกาศที่ @Taylor แม้ว่าvarจะเหมาะสมกว่าสำหรับตัวอย่างของ Sasha ในปัจจุบัน)
cregox

241

คุณสามารถทำเช่นนี้จาก Javascript 1.7 เป็นต้นไปโดยใช้"ที่ได้รับมอบหมาย destructuring" โปรดทราบว่าสิ่งเหล่านี้ไม่สามารถใช้ได้ในรุ่น Javascript ที่เก่ากว่า (ความหมาย - ไม่มีในรุ่น ECMAScript 3 หรือ 5)

อนุญาตให้คุณกำหนดตัวแปร 1+ พร้อมกัน:

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

// or

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

คุณยังสามารถใช้การทำลายวัตถุรวมกับค่าคุณสมบัติแบบย่อเพื่อตั้งชื่อค่าส่งคืนในวัตถุและเลือกสิ่งที่คุณต้องการ:

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

และโดยวิธีการที่ไม่หลงกลด้วยความจริงที่ว่า ECMAScript return 1, 2, ...ช่วยให้คุณ สิ่งที่เกิดขึ้นจริงไม่มีสิ่งที่อาจดูเหมือน การแสดงออกในการแถลงผลตอบแทน - 1, 2, 3- คืออะไร แต่ผู้ประกอบการจุลภาคนำไปใช้กับตัวอักษรที่เป็นตัวเลข ( 1, 2และ3) ตามลำดับซึ่งในที่สุดจะประเมินค่าของนิพจน์สุดท้ายของ 3- นั่นเป็นเหตุผลว่าทำไมreturn 1, 2, 3หน้าที่จึงไม่มีอะไรเหมือนกันอีกreturn 3แล้ว

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

1
สิ่งที่แปลกและน่าสนใจเกี่ยวกับตัวอย่างสุดท้าย: สำหรับfunction foo(){return 1,2,3;}การconsole.log([].push(foo()))พิมพ์ออกมา 1.
เมเรดิ ธ

@ AurélienOomsฉันรู้ในภายหลัง ขอบคุณ
เมเรดิ ธ

1
ทำไม var [x, y] = [1, 2]; x; // 1 y; // 2 มันใช้ไม่ได้กับโครม? ยกข้อผิดพลาด; ReferenceError: ด้านซ้ายมือไม่ถูกต้องในการมอบหมาย
Naveen Agarwal

1
Chrome v49 วางจำหน่ายเมื่อสัปดาห์ที่แล้วโดยสนับสนุน "การกำหนดค่าการทำลายโครงสร้าง" นอกกรอบ
Eugene Kulabuhov

1
นี่ควรเป็นคำตอบที่ได้รับการยอมรับการทำลายล้างใหม่เป็นวิธีที่ยอดเยี่ยมในการทำเช่นนี้
Jez

68

เพียงแค่คืนค่าวัตถุตามตัวอักษร

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 ฉันชอบวิธีนี้ มันอาจมีประโยชน์สำหรับฉัน คำถามหนึ่งควรจะมีความต้องการฟังก์ชั่นในการส่งคืนทุกครั้งที่ผลลัพธ์ ( result1 .. resultN ) รับฟังก์ชั่นของตัวเองหรือจะมีการใช้รหัสฟังก์ชั่นซ้ำหรือไม่ (ฉันไม่รู้ว่าจะทดสอบได้อย่างไร) TIA
Karl

44

ตั้งแต่ ES6 คุณสามารถทำได้

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

let {dCodes, dCodes2} = newCodes()

การแสดงออกของการกลับมา{dCodes, dCodes2}เป็นมูลค่าทรัพย์สินจดชวเลข{dCodes: dCodes, dCodes2: dCodes2}และเทียบเท่ากับการนี้

ที่ได้รับมอบหมายในบรรทัดสุดท้ายนี้เรียกว่าได้รับมอบหมายจะทำลายวัตถุ มันแยกค่าคุณสมบัติของวัตถุและกำหนดให้กับตัวแปรที่มีชื่อเดียวกัน หากคุณต้องการกำหนดค่าส่งคืนให้กับตัวแปรที่มีชื่อต่างกันคุณสามารถทำได้เช่นนี้let {dCodes: x, dCodes2: y} = newCodes()


27

Ecmascript 6 รวมถึง "การทำลายล้างการกำหนดค่า" (ตามที่กล่าวไว้ใน kangax) ดังนั้นในเบราว์เซอร์ทั้งหมด (ไม่ใช่แค่ Firefox) คุณจะสามารถจับภาพอาร์เรย์ของค่าโดยไม่ต้องสร้างอาร์เรย์หรือวัตถุที่มีชื่อเพื่อจุดประสงค์เดียว

//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 ได้แล้ว!


24

อีกสิ่งที่ควรค่าแก่การพูดถึงคือไวยากรณ์ที่แนะนำใหม่ (ES6) คือการใช้การสร้างวัตถุแบบย่อนอกเหนือจากการทำลายการบ้าน

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

ไวยากรณ์นี้สามารถผสมกับ babel หรือ js polyfiller อื่น ๆ สำหรับเบราว์เซอร์รุ่นเก่า แต่ตอนนี้โชคดีที่ทำงานได้ดีกับ Chrome และ Firefox รุ่นล่าสุด

แต่ในการสร้างวัตถุใหม่การจัดสรรหน่วยความจำ (และการโหลด gc ในที่สุด) มีส่วนเกี่ยวข้องที่นี่อย่าคาดหวังว่าจะได้รับประสิทธิภาพมากนัก JavaScript ไม่ใช่ภาษาที่ดีที่สุดสำหรับการพัฒนาสิ่งที่เหมาะสมที่สุดอย่างไรก็ตามหากจำเป็นคุณสามารถพิจารณานำผลลัพธ์ของคุณไปใช้กับวัตถุรอบข้างหรือเทคนิคดังกล่าวซึ่งโดยปกติแล้วจะเป็นเทคนิคการปฏิบัติทั่วไประหว่าง JavaScript, Java และภาษาอื่น ๆ


ที่ยังไม่ได้ทำงานกับ IE หรือ Edge เพียงแค่ต้องการที่จะทราบ
user1133275

เคยใช้นี่มาสักหน่อย ... มันเร็วกว่า / ราบรื่นกว่าในการใช้อาร์เรย์และหลีกเลี่ยงการสร้างวัตถุหากเป็นไปได้ตามที่แสดงโดย @ user3015682
dkloke

18

วิธีที่ดีที่สุดสำหรับเรื่องนี้คือ

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

จากนั้นใช้

a().f

คืน 4

ใน ES6 คุณสามารถใช้รหัสนี้

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

จากนั้นเรียกใช้ฟังก์ชันอีกครั้งสำหรับแต่ละตัวแปรหรือไม่ นั่นไม่ใช่วิธีที่ดีที่สุด
Elia Iliashenko

ฟังก์ชันนี้คืนค่าหลายค่าอาจไม่ใช่วิธีที่ดีที่สุด
Behnam Mohammadi

ทุกครั้งที่ล่ามเป็นไปตาม () มันจะเรียกใช้ฟังก์ชันอีกครั้ง ดังนั้น var f = a (). f; var c = a (). c; var d = a (). d; จะเปิดตัว () สามครั้งซึ่งมีแนวโน้มที่จะสูญเสียประสิทธิภาพ วิธีที่ดีกว่าคือ var result = a (); var f = result.f; ฯลฯ
Elia Iliashenko

1
ตกลงเพื่อประสิทธิภาพที่ดีขึ้นคุณสามารถรักษาค่าให้กับตัวแปรและใช้งานได้เช่น var result = a (); และใช้ value result.d หรือ result.c และ result.f ดังนั้นในครั้งเดียวให้เรียกใช้ฟังก์ชัน ()
Behnam Mohammadi

9

นอกเหนือจากการส่งคืนอาร์เรย์หรือวัตถุตามที่ผู้อื่นแนะนำคุณสามารถใช้ฟังก์ชันตัวสะสม (คล้ายกับที่พบในThe Little Schemer ):

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

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

ฉันทำการทดสอบ jsperf เพื่อดูว่าหนึ่งในสามวิธีนั้นเร็วกว่ากัน อาร์เรย์นั้นเร็วที่สุดและตัวรวบรวมช้าที่สุด

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


โดยทั่วไปแล้วcollectorจะเรียกว่าcontinuationและเทคนิคที่เรียกว่าCPS
ceving

7

ใน JS เราสามารถคืนค่า tuple ด้วยอาเรย์หรือวัตถุได้อย่างง่ายดาย แต่อย่าลืม! => JS เป็นcallbackภาษาที่มุ่งเน้นและมีความลับเล็กน้อยสำหรับ "การคืนค่าหลายค่า" ที่ยังไม่มีใครพูดถึงลองสิ่งนี้:

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

กลายเป็น

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

:)

แบม! นี่เป็นอีกวิธีหนึ่งในการแก้ปัญหาของคุณ


6

การเพิ่มส่วนที่สำคัญที่ขาดหายไปเพื่อทำให้คำถามนี้เป็นแหล่งข้อมูลที่สมบูรณ์เนื่องจากเกิดขึ้นในผลการค้นหา

การทำลายล้างวัตถุ

ในการทำลายวัตถุคุณไม่จำเป็นต้องใช้ค่าคีย์เดียวกับชื่อตัวแปรของคุณคุณสามารถกำหนดชื่อตัวแปรอื่นได้โดยการกำหนดดังต่อไปนี้:

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

การทำลายล้างอาร์เรย์

ในการทำลายอาร์เรย์คุณสามารถข้ามค่าที่คุณไม่ต้องการได้

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

มันคุ้มค่าที่...restจะสังเกตว่ามันควรจะจบในตอนท้ายเพราะมันไม่สมเหตุสมผลที่จะทำลายอะไรหลังจากที่ทุกอย่างถูกรวมเข้าrestด้วยกัน

ฉันหวังว่านี่จะเพิ่มคุณค่าให้กับคำถามนี้ :)


5

คุณยังสามารถทำสิ่งต่อไปนี้

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

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

5

วิธีทั่วไปในการส่งคืนค่าหลายค่าในจาวาสคริปต์คือการใช้ตัวอักษรของวัตถุดังนั้นสิ่งที่ต้องการ:

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

และรับค่าเช่นนี้:

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

หรือแม้แต่วิธีที่สั้นกว่า:

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

และทำให้พวกเขาเป็นรายบุคคลเช่น:

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

4

คุณสามารถใช้ "วัตถุ"

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

    return obj;
}

1
นี่คือวิธีที่จะไปสำหรับ IE ใช้ในภายหลังเช่น: let obj = newCodes (); การแจ้งเตือน (obj.dCodes);
Asen Kasimov

3

ถูกต้องทั้งหมด returnประมวลผลเชิงตรรกะจากซ้ายไปขวาและส่งคืนค่าสุดท้าย

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

>> foo()
>> 3

1
,เป็นผู้ดำเนินการและสามารถนำมาใช้ในการแสดงออกใด ๆ ไม่มีอะไรพิเศษเกี่ยวกับreturnที่นี่
gman


2

ฉันรู้วิธีการนี้สองวิธี: 1. กลับมาเป็นอาร์เรย์ 2. กลับมาเป็นวัตถุ

นี่คือตัวอย่างที่ฉันพบ:

<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

ไม่กี่วันที่ผ่านมาฉันมีความต้องการคล้ายกันในการรับค่าส่งคืนหลายค่าจากฟังก์ชันที่ฉันสร้างขึ้น

จากค่าส่งคืนจำนวนมากฉันต้องการให้ส่งคืนเฉพาะค่าเฉพาะสำหรับเงื่อนไขที่กำหนดแล้วค่าส่งคืนอื่น ๆ ที่สอดคล้องกับเงื่อนไขอื่น ๆ


นี่คือตัวอย่างของวิธีที่ฉันทำ:

ฟังก์ชั่น:

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

การรับค่าส่งคืนที่ต้องการจากวัตถุที่ส่งคืนโดยฟังก์ชัน:

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

จุดรวมของการตอบคำถามนี้คือการแบ่งปันวิธีการรับ Date ในรูปแบบที่ดี หวังว่ามันจะช่วยคุณ :)


1

ฉันไม่มีอะไรเพิ่มที่นี่ใหม่ แต่เป็นอีกวิธีหนึ่ง

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

0

ดีเราไม่สามารถทำสิ่งที่คุณพยายาม แต่สิ่งที่น่าจะทำได้ด้านล่าง

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

จากนั้นเมื่อเรียกวิธีการ

const {x,y} = multiReturnValues();

console.log(x) ---> 10
console.log(y) ---> 20
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.