Trả về nhiều giá trị trong JavaScript?


846

Tôi đang cố gắng trả lại hai giá trị trong JavaScript . Điều này có thể không?

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

bạn có thể giải quyết điều này bằng cách sử dụng các cuộc gọi lại, nếu bạn sẵn sàng làm như vậy, hãy xem câu trả lời của tôi. Mọi người quên rằng bạn có thể "trả lại nhiều giá trị" một cách dễ dàng bằng JS, bằng cách sử dụng bộ dữ liệu hoặc thậm chí: gọi lại!
Alexander Mills

16
Các câu trả lời đã lỗi thời. Bây giờ có thể. 2ality.com/2014/06/es6-multipl-return-values.html
Erel Segal-Halevi

3
Về mặt kỹ thuật, bạn vẫn đang trả về một đối tượng / mảng duy nhất, đó chỉ là cấu trúc giải mã đơn giản hơn trong ES6.
Andrea Bergonzo

Câu trả lời:


1298

Không, nhưng bạn có thể trả về một mảng chứa các giá trị của bạn:

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

Sau đó, bạn có thể truy cập chúng như vậy:

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

Với cú pháp ECMAScript 6 mới nhất *, bạn cũng có thể hủy cấu trúc giá trị trả về bằng trực giác hơn:

const [first, second] = getValues();

Nếu bạn muốn đặt "nhãn" cho mỗi giá trị được trả về (dễ duy trì hơn), bạn có thể trả về một đối tượng:

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

Và để truy cập chúng:

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

Hoặc với cú pháp ES6:

const {first, second} = getValues();

* Xem bảng này để tương thích trình duyệt. Về cơ bản, tất cả các trình duyệt hiện đại ngoài IE đều hỗ trợ cú pháp này, nhưng bạn có thể biên dịch mã ES6 xuống JavaScript tương thích với IE trong thời gian xây dựng với các công cụ như Babel .


151
Hoặc bạn có thể trả về một đối tượng: return {dCodes : dCodes, dCodes2 : dCodes2};để dễ tham khảo hơn.
Intelekshual

10
bạn thậm chí có thể trả về một đối tượng {: dCodes: dCodes, dCodes2: dCodes2} về mặt chức năng giống nhau nhưng khi bạn tham chiếu đối tượng trả về của mình, bạn có một mã dễ đọc hơn một chút là obj.dCodes và obj.dCodes2 vs obj [0] và obj [1] ]
Jonathan S.

1
@alexela Chắc chắn bạn chỉ cần sử dụng var dCodes = newCodes (). dCodes; var dCodes2 = newCodes (). dCodes2 Tuy nhiên, bạn sẽ gọi hàm hai lần có thể gây lãng phí tài nguyên nếu nó phức tạp.
Vadim Kirilchuk

12
@VadimKirilchuk Không cần phải gọi nó hai lần với nhiệm vụ hủy hoại - ví dụ. const { dCodes, dCodes2 } = newCodes();
Taylor Edmiston

7
như các câu trả lời khác đã nói (và ý kiến ​​ngụ ý), ES6 mang đến một vài lựa chọn ở đây. Chính xác là 3: (1) tốc ký thuộc tính đối tượng return {dCodes, dCodes2} hoạt động giống như @Intelekshual đã đề cập và (2) sử dụng cùng chức năng mà bạn có thể truy cập chúng bằng cách phá hủy mảng [dCodes, dCodes2] = newCodes()hoặc (3) đối tượng ({dCodes, dCodes2} = newCodes())(không cần sử dụng khai báo ở đó @Taylor , mặc dù varsẽ phù hợp hơn với ví dụ của Sasha hiện tại).
cregox

241

Bạn có thể thực hiện việc này từ Javascript 1.7 trở đi bằng cách sử dụng "hủy bài tập" . Lưu ý rằng những điều này không có sẵn trong các phiên bản Javascript cũ hơn (có nghĩa là - không phải với phiên bản thứ 3 hoặc thứ 5 của ECMAScript).

Nó cho phép bạn gán cho 1+ biến đồng thời:

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

// or

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

Bạn cũng có thể sử dụng hàm hủy đối tượng kết hợp với tốc ký giá trị thuộc tính để đặt tên cho các giá trị trả về trong một đối tượng và chọn ra các giá trị bạn muốn:

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

Và nhân tiện, đừng để bị lừa bởi thực tế là ECMAScript cho phép bạn return 1, 2, .... Những gì thực sự xảy ra ở đó không phải là những gì có vẻ. Một biểu thức trong câu lệnh return - 1, 2, 3- là gì, nhưng một nhà điều hành dấu phẩy áp dụng cho literals số ( 1, 23) tuần tự, mà cuối cùng để đánh giá giá trị của biểu thức cuối cùng của nó - 3. Đó là lý do tại sao return 1, 2, 3chức năng giống hệt như không có gì hơn nhưng return 3.

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

1
Điều kỳ lạ và thú vị về các ví dụ cuối cùng: một function foo(){return 1,2,3;}làm console.log([].push(foo()))in ra 1.
Meredith

@ AurélienOoms Tôi nhận ra sau này. Cảm ơn
Meredith

1
tại sao var [x, y] = [1, 2]; x; // 1 y; // 2 cái này không hoạt động trong chrome? đưa ra một lỗi; ReferenceError: Bên trái chuyển nhượng không hợp lệ
Naveen Agarwal

1
Chrome v49 đã được phát hành một tuần trước hỗ trợ "phá hủy bài tập" bên ngoài.
Eugene Kulabuhov

1
Đây phải là câu trả lời được chấp nhận - phá hủy mới là một cách tuyệt vời để làm điều này.
Jez

68

Chỉ cần trả lại một đối tượng theo nghĩa đen

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 Tôi thích giải pháp này. Nó có thể hữu ích cho tôi. Một câu hỏi, nếu cần phải có hàm trả về thì mọi trường hợp kết quả ( result1 .. resultN ) có được bản sao của hàm đó không hoặc có sử dụng lại mã chức năng không? (Tôi không biết làm thế nào tôi có thể kiểm tra điều này.) TIA.
Karl

44

Vì ES6 bạn có thể làm điều này

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

let {dCodes, dCodes2} = newCodes()

Biểu thức trả về {dCodes, dCodes2}là tốc ký giá trị thuộc tính và tương đương với giá trị này {dCodes: dCodes, dCodes2: dCodes2}.

Nhiệm vụ này trên dòng cuối cùng được gọi là phân công phá hủy đối tượng . Nó trích xuất giá trị thuộc tính của một đối tượng và gán nó cho biến có cùng tên. Nếu bạn muốn gán giá trị trả về cho các biến có tên khác nhau, bạn có thể làm như thế nàylet {dCodes: x, dCodes2: y} = newCodes()


27

Ecmascript 6 bao gồm "hủy các bài tập" (như kangax đã đề cập), vì vậy trong tất cả các trình duyệt (không chỉ Firefox), bạn sẽ có thể chụp một mảng các giá trị mà không phải tạo một mảng hoặc đối tượng được đặt tên cho mục đích duy nhất là bắt chúng.

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

Bạn có thể dùng thử trong Firefox rồi!


24

Một cú pháp đáng nói khác được đề cập (ES6) là sử dụng tốc ký tạo đối tượng bên cạnh việc hủy bỏ nhiệm vụ.

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

Cú pháp này có thể được điền đầy đủ với babel hoặc các polyfiller js khác cho các trình duyệt cũ hơn nhưng may mắn là bây giờ hoạt động tự nhiên với các phiên bản gần đây của Chrome và Firefox.

Nhưng khi tạo một đối tượng mới, việc cấp phát bộ nhớ (và tải gc cuối cùng) có liên quan ở đây, đừng mong đợi nhiều hiệu suất từ ​​nó. JavaScript không phải là ngôn ngữ tốt nhất để phát triển những thứ tối ưu cao, nhưng nếu cần, bạn có thể xem xét đưa kết quả của mình lên đối tượng xung quanh hoặc các kỹ thuật như vậy thường là các thủ thuật hiệu suất phổ biến giữa JavaScript, Java và các ngôn ngữ khác.


Điều đó chưa làm việc trên IE hoặc Edge, chỉ muốn lưu ý.
dùng1133275

Được sử dụng khá nhiều ... việc sử dụng một mảng nhanh hơn / mượt mà hơn và tránh xây dựng một đối tượng nếu có thể như được hiển thị bởi @ user3015682.
dkloke

18

Cách tốt nhất cho việc này là

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

Sau đó sử dụng

a().f

trở về 4

trong ES6 bạn có thể sử dụng mã này

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

Sau đó chạy lại hàm cho từng biến? Đó không phải là cách tiếp cận tốt nhất.
Elia Iliashenko

Hàm này trả về giá trị đa, có thể không phải là cách tiếp cận tốt nhất.
Behnam Mohammadi

Mỗi khi trình thông dịch gặp một () nó sẽ chạy lại hàm. Vậy, var f = a (). F; var c = a (). c; var d = a (). d; sẽ khởi chạy một () ba lần, dễ bị mất hiệu năng. Cách tiếp cận tốt hơn sẽ là var result = a (); var f = result.f; v.v.
Elia Iliashenko

1
ok để có hiệu suất tốt hơn, bạn có thể giữ giá trị cho một biến và sử dụng nó, ví dụ var result = a (); và sử dụng giá trị result.d hoặc result.c và result.f, vì vậy chỉ cần một lần chạy hàm ().
Behnam Mohammadi

9

Khác với việc trả về một mảng hoặc một đối tượng như những người khác đã khuyến nghị, bạn cũng có thể sử dụng hàm collector (tương tự như hàm được tìm thấy trong The Little Schemer ):

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

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

Tôi đã thực hiện một thử nghiệm jsperf để xem một trong ba phương pháp nhanh hơn. Mảng là nhanh nhất và collector là chậm nhất.

http://jsperf.com/retinating-mult Môn-value-2


Thông thường collectorđược gọi continuationvà kỹ thuật được gọi là CPS
ceving

7

Trong JS, chúng ta có thể dễ dàng trả về một tuple với một mảng hoặc đối tượng, nhưng đừng quên! => JS là một callbackngôn ngữ được định hướng và có một bí mật nhỏ ở đây để "trả lại nhiều giá trị" mà chưa ai đề cập, hãy thử điều này:

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

trở thành

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

:)

bam Đây chỉ đơn giản là một cách khác để giải quyết vấn đề của bạn.


6

Thêm các phần quan trọng còn thiếu để làm cho câu hỏi này trở thành một tài nguyên hoàn chỉnh, vì điều này xuất hiện trong kết quả tìm kiếm.

Phá hủy đối tượng

Trong việc hủy đối tượng, bạn không nhất thiết phải sử dụng cùng một giá trị khóa với tên biến của mình, bạn có thể gán một tên biến khác bằng cách định nghĩa nó như sau:

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

Phá hủy mảng

Trong phá hủy mảng, bạn có thể bỏ qua các giá trị bạn không cần.

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

Điều đáng chú ý là ...restluôn luôn phải ở cuối vì nó không có ý nghĩa gì để phá hủy bất cứ thứ gì sau khi mọi thứ khác được tổng hợp thànhrest .

Tôi hy vọng điều này sẽ thêm một số giá trị cho câu hỏi này :)


5

Bạn cũng có thể làm:

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

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

5

Một cách rất phổ biến để trả về nhiều giá trị trong javascript là sử dụng một đối tượng bằng chữ , vì vậy đại loại như:

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

và nhận các giá trị như thế này:

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

hoặc thậm chí một cách ngắn hơn:

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

và nhận chúng riêng lẻ như:

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

4

Bạn có thể sử dụng "Đối tượng"

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

    return obj;
}

1
Đây là cách để đi cho IE. Sau này sử dụng như: let obj = newCodes (); cảnh báo (obj.dCodes);
Asen Kasimov

3

Tất cả đều đúng. returnxử lý logic từ trái sang phải và trả về giá trị cuối cùng.

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

>> foo()
>> 3

1
những ,là một nhà điều hành và có thể được sử dụng trong bất kỳ biểu hiện. Không có gì đặc biệt returnở đây.
gman


2

Tôi biết hai cách để làm điều này: 1. Trả về dưới dạng Mảng 2. Trả về làm Đối tượng

Đây là một ví dụ tôi tìm thấy:

<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

Vài ngày trước tôi có yêu cầu tương tự là nhận được nhiều giá trị trả về từ một hàm mà tôi đã tạo.

Từ nhiều giá trị trả về, tôi cần nó chỉ trả về giá trị cụ thể cho một điều kiện nhất định và sau đó là giá trị trả về khác tương ứng với điều kiện khác.


Đây là ví dụ về cách tôi đã làm điều đó:

Chức năng:

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

Nhận giá trị trả về bắt buộc từ đối tượng được trả về bởi hàm:

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

Toàn bộ quan điểm của việc trả lời câu hỏi này là chia sẻ cách tiếp cận nhận Ngày này ở định dạng tốt. Hy vọng nó đã giúp bạn :)


1

Tôi không có gì thêm mới ở đây nhưng một cách khác.

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

0

Vâng, chúng tôi không thể chính xác làm những gì bạn đang cố gắng. Nhưng một cái gì đó có khả năng dưới đây có thể được thực hiện.

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

Sau đó khi gọi phương thức

const {x,y} = multiReturnValues();

console.log(x) ---> 10
console.log(y) ---> 20
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.