Вернуть несколько значений в JavaScript?

847

Я пытаюсь вернуть два значения в JavaScript . Это возможно?

var newCodes = function() {  
    var dCodes = fg.codecsCodes.rs;
    var dCodes2 = fg.codecsCodes2.rs;
    return dCodes, dCodes2;
};
Асим Заиди
источник
Вы можете решить эту проблему с помощью обратных вызовов, если вы хотите это сделать, см. мой ответ. Люди забывают, что вы можете легко «возвращать несколько значений» с помощью JS, используя кортежи или даже: обратные вызовы!
Александр Миллс
16
Ответы устарели. Теперь это возможно. 2ality.com/2014/06/es6-multiple-return-values.html
Сегал-Галеви,
3
Технически вы все еще возвращаете один объект / массив, это просто деконструкция, которая проще в ES6.
Андреа Бергонзо

Ответы:

1302

Нет, но вы можете вернуть массив, содержащий ваши значения:

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 во время сборки с помощью таких инструментов, как Babel .

Саша Чедыгов
источник
151
Или вы можете вернуть объект: return {dCodes : dCodes, dCodes2 : dCodes2};чтобы было легче ссылаться.
Интелекшуал
10
Вы могли бы даже вернуть объект {: dCodes: dCodes, dCodes2: dCodes2} функционально так же, но когда вы ссылаетесь на ваш возвращенный объект, вы получаете немного более читаемый код как obj.dCodes и obj.dCodes2 против obj [0] и obj [1 ]
Джонатан С.
1
@alexela Конечно, вы можете просто использовать var dCodes = newCodes (). dCodes; var dCodes2 = newCodes (). dCodes2 Однако вы вызовете функцию дважды, что может быть пустой тратой ресурсов, если она сложная.
Вадим Кирилчук
12
@VadimKirilchuk Нет необходимости дважды звонить с деструктивным заданием - напр. const { dCodes, dCodes2 } = newCodes();
Тейлор
7
Как сказали другие ответы (и подразумеваемые комментарии), ES6 предлагает несколько вариантов. 3, если быть точным: (1) сокращение свойства объекта return {dCodes, dCodes2} работает так же, как упомянутое @Intelekshual, и (2) используя ту же функцию, к которой вы можете просто обращаться с помощью массивов деструктурирования [dCodes, dCodes2] = newCodes()или (3) объектов ({dCodes, dCodes2} = newCodes())(нет необходимости использовать объявление там @Taylor Правда, это varбыло бы более подходящим для текущего примера Саши).
Cregox
241

Вы можете сделать это начиная с Javascript 1.7 и далее, используя «деструктурирующие назначения» . Обратите внимание, что они недоступны в более старых версиях 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;
kangax
источник
1
Странная и интересная вещь в последнем примере: для function foo(){return 1,2,3;}выполнения console.log([].push(foo()))распечатывается 1.
Мередит
@ AurélienOoms Я понял позже. Спасибо
Мередит
1
почему var [x, y] = [1, 2]; Икс; // 1 год; // 2 это не работает в Chrome? поднять ошибку; ReferenceError: Недопустимая левая часть в назначении
Навин Агарвал
1
Chrome v49 был выпущен неделю назад с поддержкой «деструктурирующих заданий».
Евгений Кулабухов
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.
Карл
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()

Peracek
источник
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 уже!

user3015682
источник
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.
17
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}
}
Бехнам Мохаммади
источник
Затем снова запустите функцию для каждой переменной? Это не лучший подход.
Элия ​​Ильяшенко
эта функция возвращает множественное значение, возможно, это не лучший подход.
Бехнам Мохаммади
Каждый раз, когда интерпретатор встречает (), он снова запускает функцию. Итак, var f = a (). F; var c = a (). c; var d = a (). d; запустит () три раза, что может привести к потере производительности. Лучшим подходом было бы var result = a (); var f = result.f; и т. д.
Элия ​​Ильяшенко
1
Хорошо, для лучшей производительности вы можете сохранить значение в переменной и использовать его, например, var result = a (); и используйте значения result.d или result.c и result.f, чтобы просто запустить функцию ().
Бехнам Мохаммади
9

Кроме возврата массива или объекта, как рекомендовали другие, вы также можете использовать функцию сборщика (аналогичную той, что была найдена в «Маленьком интрижке» ):

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 мы можем легко вернуть кортеж с массивом или объектом, но не забывайте! => 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

Очень распространенный способ вернуть несколько значений в javascript - это использование литералов объекта , что-то вроде:

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;
}
Sebu
источник
1
Это путь для IE. Позже используйте как: let obj = newCodes (); оповещения (obj.dCodes);
Асен Касимов
3

Все правильно. returnлогически обрабатывает слева направо и возвращает последнее значение.

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

>> foo()
>> 3
Артемий
источник
1
,является оператором и может быть использован в любом выражении. Здесь нет ничего особенного return.
Ган
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;
}

Получение Required возвращаемого значения из объекта, возвращаемого функцией:

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

Весь смысл ответа на этот вопрос состоит в том, чтобы поделиться этим подходом получения даты в хорошем формате. Надеюсь, это помогло вам :)

Крупеш Анадкат
источник
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
Anjana
источник