Повернути кілька значень у JavaScript?


844

Я намагаюся повернути два значення в 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 простіше.
Андреа Бергонцо

Відповіді:


1295

Ні, але ви можете повернути масив, що містить ваші значення:

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};полегшити посилання.
Intelekshual

10
ви можете навіть повернути об’єкт {: dCodes: dCodes, dCodes2: dCodes2} функціонально однаково, але коли ви посилаєтесь на повернутий об'єкт, у вас є трохи більше читабельний код як obj.dCodes і obj.dCodes2 vs 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адекватніше підходить для прикладу поточного Саші).
Крегокс

241

Це можна зробити з Javascript 1.7, використовуючи "завдання деструктирування" . Зауважте, що вони недоступні у старих версіях Javascript (тобто - ні з 3-м, ні з 5-м виданнями ECMAScript).

Це дозволяє одночасно призначити 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]; х; // 1 у; // 2 це не працює в хромі? підвищити помилку; ReferenceError: Недійсний лівий бік у завданні
Naveen Agarwal

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


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

Цей синтаксис може бути заповнений бабелом або іншим js поліфіллером для старих веб-переглядачів, але, на щастя, зараз він працює з останніми версіями Chrome і Firefox.

Але для створення нового об'єкта тут задіяно розподіл пам'яті (і можливе завантаження gc), не чекайте від нього великої продуктивності. JavaScript не є найкращою мовою для розробки вкрай оптимальних речей, але якщо це потрібно, ви можете розглянути можливість розміщення результатів на навколишньому об'єкті або таких техніках, які зазвичай є загальноприйнятими прийомами роботи між JavaScript, Java та іншими мовами.


Це ще не працює над IE або Edge, просто хотів зазначити.
користувач1133275

Використовуючи це зовсім небагато ... швидше / плавніше використовувати масив і уникати побудови об'єкта, якщо це можливо, як показано на @ 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}
}

Потім запустити функцію знову для кожної змінної? Це не найкращий підхід.
Елія Іліашенко

ця функція повертає багатозначне значення, можливо, це не найкращий підхід.
Бенам Мохаммаді

Кожен раз, коли перекладач зустрічає (), він знову запускає функцію. Отже, var f = a (). F; var c = a (). c; var d = a (). d; запустить () три рази, що схильне до втрати продуктивності. Кращим підходом буде var результат = a (); var f = результат.f; пр.
Елія Ілляшенко

1
ОК для кращої продуктивності, ви можете зберегти значення змінної та використовувати її, наприклад, var rezultat = a (); і використовуйте значення result.d або result.c і result.f, тож за один раз запустіть функцію ().
Бенам Мохаммаді

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
закінчення

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

Дуже розповсюдженим способом повернення кількох значень у 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;
}

1
Це шлях для IE. Пізніше використовувати як: нехай obj = newCodes (); попередження (obj.dCodes);
Асен

3

Все правильно. returnлогічно обробляється зліва направо і повертає останнє значення.

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

>> foo()
>> 3

1
the ,є оператором і може використовуватися в будь-якому виразі. Тут немає нічого особливого 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;

Весь сенс відповіді на це питання полягає в тому, щоб поділитися таким підходом щодо отримання Дати у хорошому форматі. Сподіваюся, це допомогло вам :)


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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.