Когда мне следует использовать `return` в функциях стрелки es6?

Ответы:

262

Джексон частично ответил на аналогичный вопрос:

Неявный возврат, но только если блока нет.

  • Это приведет к ошибкам, когда однострочник расширяется до нескольких строк, и программист забывает добавить a return.
  • Неявное возвращение синтаксически неоднозначно. (name) => {id: name}возвращает объект {id: name}... верно? Неправильно. Это возвращается undefined. Эти фигурные скобки являются явным блоком. id:это ярлык.

Я бы добавил к этому определение блока :

Оператор блока (или составной оператор на других языках) используется для группировки нуля или более операторов. Блок ограничен парой фигурных скобок.

Примеры :

// returns: undefined
// explanation: an empty block with an implicit return
((name) => {})() 

// returns: 'Hi Jess'
// explanation: no block means implicit return
((name) => 'Hi ' + name)('Jess')

// returns: undefined
// explanation: explicit return required inside block, but is missing.
((name) => {'Hi ' + name})('Jess')

// returns: 'Hi Jess'
// explanation: explicit return in block exists
((name) => {return 'Hi ' + name})('Jess') 

// returns: undefined
// explanation: a block containing a single label. No explicit return.
// more: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/label
((name) => {id: name})('Jess') 

// returns: {id: 'Jess'}
// explanation: implicit return of expression ( ) which evaluates to an object
((name) => ({id: name}))('Jess') 

// returns: {id: 'Jess'}
// explanation: explicit return inside block returns object
((name) => {return {id: name}})('Jess') 
Джесс Телфорд
источник
Я не понимаю этот синтаксис ... вы создаете класс с использованием класса littoral и затем вызываете неявный конструктор с одним аргументом ('Jess') ?? Я думал, что вы к этому ((имя) => ({id: 'Jess'}))
Майкл Даусманн
3
@MichaelDausmann Это функция со стрелкой, имеющая один параметр, nameс функцией, заключенной в круглые скобки и вызываемой с одним аргументом «Jess». Код между =>и )('Jess')в каждом случае является телом функции стрелки. Рассматривайте это как краткую форму выражения «Немедленно вызванная функция»(function (name) { return { id: name } })('Jess')
Russ Cam
Очень полезный индд! помогает выявить проблемы в Promises.all, которые отображают элементы с помощью функции стрелки, и вы можете заметить, если получите массив неопределенный, если не было возвращено значение для отображения на массив с помощью функций стрелки.
Джей Шах
Что было бы обратной стороной систематического неявного возврата для функций стрелок? Точно так же, как это делает coffeescript ... (хотя я не люблю coffeescript)
Августин Ридингер
4
Чтобы было ясно, кажется, что, поскольку JS-синтаксический анализатор не знает, следует ли ожидать выражение (например, выражение, содержащее литерал объекта {}) или блок , он предполагает, что a { }обозначает блок. Это означает, что когда он видит id: name, он думает, что id:является выражением, создающим метку (очень редко используемая особенность JS, которая имеет дело с управлением потоком и использует a :), а затем nameследующее id:является просто отдельным оператором, который содержит только переменную name(& ничего не делает).
Ионо
18

Я понимаю это правило ...

Для функций, которые эффективно трансформируются (однострочные манипуляции с аргументами), return является неявным.

Кандидатами являются:

// square-root 
value => Math.sqrt(value)

// sum
(a,b) => a+b

Для других операций (более чем в одной строке, требующих блока, return должен быть явным

Amarsh
источник
11

Здесь есть еще один случай.

При написании функционального компонента в React вы можете использовать скобки для неявного переноса возвращаемого JSX.

const FunctionalComponent = () => (
  <div>
    <OtherComponent />
  </div>
);
дей
источник
4
Вы всегда можете использовать круглые скобки, это не связано с JSX или React.
Эмиль Бержерон
4

Вот еще один случай, который доставил мне некоторые проблемы.

// the "tricky" way
const wrap = (foo) => (bar) => {
  if (foo === 'foo') return foo + ' ' + bar;
  return 'nofoo ' + bar;
}

Здесь мы определяем функцию, возвращающую анонимную функцию. «Хитрый» бит в том, что тело функции для внешней функции (часть, начинающаяся с (bar) => ...) визуально выглядит как «блок», но это не так. Так как это не так, неявное возвращение вступает в силу.

Вот как будет выполняться перенос:

// use wrap() to create a function withfoo()
const withfoo = wrap('foo');
// returns: foo bar
console.log(withfoo('bar'));

// use wrap() to create a function withoutfoo()
const withoutfoo = wrap('bar');
// returns: nofoo bar
console.log(withoutfoo('bar'));

Способ, которым я распаковал это, чтобы удостовериться, что я понял, состоял в том, чтобы "разархивировать" функции.

Вот семантический эквивалент первого блока кода, просто заставляющий тело wrap () делать явный возврат. Это определение дает те же результаты, что и выше. Это где точки соединяются. Сравните первый блок кода выше с приведенным ниже, и станет ясно, что сама функция стрелки обрабатывается как выражение, а не как блок, и имеет подразумеваемый возврат .

// the explicit return way
const wrap = (foo) => {
  return (bar) => {
    if (foo === 'foo') return foo + ' ' + bar;
    return 'nofoo ' + bar;
  }
}

Полная версия обертки была бы такой, которая не так компактна, как версия с жирными стрелками, но кажется, что ее легче понять.

// the "no arrow functions" way
const wrap = function(foo) {
  return function(bar) {
    if (foo === 'foo') return foo + ' ' + bar;
    return 'nofoo ' + bar;
  };
};

В конце концов, для других, которым, возможно, придется читать мой код, и для будущего, я думаю, я бы предпочел использовать версию без стрелки, которая может быть понятна на первый взгляд, а не версию со стрелкой, которая занимает немало времени. думал (и в моем случае эксперименты), чтобы впасть.

grayjohn
источник
3

Функции стрелок позволяют получить неявный возврат: значения возвращаются без использования returnключевого слова.

Работает, когда в теле функции есть оператор on-line:

const myFunction = () => 'test'

console.log(myFunction()) //'test'

Другой пример, возвращающий объект (не забудьте заключить фигурные скобки в круглые скобки, чтобы он не рассматривался в скобках тела функции обтекания):

const myFunction = () => ({value: 'test'})

console.log(myFunction()) //{value: 'test'}

Флавио Копес
источник
1
Это должен быть правильный ответ, хотя и требует немного большего объяснения. В основном, когда тело функции является выражением, а не блоком, значение этого выражения возвращается неявно. Поправьте меня если я ошибаюсь.
Пол-Себастьян Маноле