Чи можна використовувати синтаксис функції стрілки ES6 з генераторами? (позначення стрілки)


243

тобто як я це висловлюю:

function *(next) {}

зі стрілками. Я спробував усі комбінації, про які я міг придумати, і не можу знайти жодної документації на нього.

(наразі використовується вузол v0.11.14)


5
Ви не можете. Вибачте. "Оператор function*(ключове слово функції з подальшим зірочкою) визначає функцію генератора."

2
Зауважте, що на цій темі на esdiscuss.org була дещо тривала дискусія на цю тему .
voithos

4
Що ви очікуєте param*=>{ }зробити?
CoderPi

4
ви знаєте, що function(){}це не так, як ()=>{}?
CoderPi

8
" це справді, що генератори ES6 роблять 2 кроки вперед і 1 крок назад? " - ні, генератори можуть лише зробити крок вперед :-)
Бергі

Відповіді:


231

Чи можна використовувати синтаксис функції стрілки ES6 з генераторами?

Ви не можете. Вибачте.

За даними MDN

Оператор function*( functionключове слово з подальшим зірочкою) визначає функцію генератора.

З специфічного документа (мій акцент):

Функція синтаксис розширено , щоб додати додатковий *маркер:

FunctionDeclaration: "function" "*"? Identifier "(" FormalParameterList? ")" 
  "{" FunctionBody "}"

175
Мені здається недоліком дизайну.
Джонатан

23
@Jonathon: Ні. Функції стрілок мають бути легкими (і не мають, .prototypeнаприклад), і часто однолінійними, тоді як генератори - навпаки.
Бергі

38
Я вже зіткнувся з кількома сценаріями, коли генератор, в який я грав, потребував доступу до попереднього this, і мені довелося написати let self = thisхак, щоб отримати доступ до нього всередині генератора. Лексичний обсяг + синтаксис стрілки було б добре. Нещасний, але не зовсім кінець світу.
dvlsg

3
Дещо додаткового контексту навколо цього в есдискусі
Нік Томлін

20
@ Бергі міркування функцій стрілок набагато складніше, ніж це. Мова йде не про стислість. Функції стрілки не повинні бути легкими - правда, є необов'язковий синтаксис тіла з одним оператором, але що робити. Багато людей використовують стрілки для всіх визначень функцій, за винятком методів класу, і занижують functionключове слово як «погану частину» мови. Для цього є вагомі причини. Для цих людей відсутність генераторів стріл - це дратівлива непослідовність.
callum

131

Різниця між Inline-функціями та Arrow-функціями

Перш за все, функції Arrow () => {} не створені для заміни Inline-функцій, function(){}і вони різні. Вбудовані функції - це просто функції, тому питання полягає в тому, чим відрізняються функції стрілок від вбудованих функцій.

Функція стрілка вираз (також відомий як функції стрілка) має більш короткий синтаксис по порівнянні з функціональними виразами і не пов'язує свою власну this, arguments, super, або new.target). Функції стрілок завжди анонімні.

Ще кілька швидких подробиць тут


Чому Arrow-функцію не можна використовувати як генератори

https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions

Використання ключового слова дохідності

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

Зауважте, що без генераторівyield немає сенсу.


Чому стрілка-функція не може використовувати врожайність

http://tc39wiki.calculist.org/es6/arrow-functions/

Функції стрілки пов'язуються thisлексично, зв'язуються returnу корпусі блоку блоку, щоб вона поверталася з функції безпосередньо стрілки, що додається, та виключає breakта continueпосилається на оператори поза функцією стрілки, що негайно додається.

Ідентифікатор первинне вираження argumentsне може бути використано в тілі функцію стріли (будь то вираз або блок - форми).

Так само yieldне можна використовувати в тілі функції стрілки. Стрілки не можуть бути генераторами, і ми не хочемо глибоких продовжень.

Вихід у функції стрілки призведе до смислової помилки: http://www.ecma-international.org/

Зрештою, причина полягає в глибокій складності впровадження ECMA6. C # не дозволяє цього також з дещо подібних причин .


3
Я скористався пошуковою системою і опублікував ще одне Пояснення для вас
CoderPi

1
Я все ще думаю, що додавання пояснень про ()=>{}багато чого допоможе, зрозуміти її відмінність від вбудованої функції та чому для генераторів існує обмеження.
vitaly-t

63
Я намагаюся з’ясувати, чому *() => { yield bla; }це не нормально, але async () => { await bla; }це ...
Лі Бенсон

7
@CodeiSir, Re " і ми не хочемо глибоких продовжень ", хитрі виправдання.
Pacerier

9
Ваш аргумент циклічний. Ви кажете, що функції стрілок не можуть бути генераторами, оскільки вони не можуть містити в них ключове слово дохід. Але вони не можуть мати ключове слово прибутковості, тому що вони не можуть бути генераторами: "Стрілки не можуть бути генераторами, і ми не хочемо глибокого продовження".
Thayne

35

Окрім дискусії на esdiscuss.org та зауважень про засідання Комітету Ecma TC39 ES6 від листопада 2013 року, зазначених вище, стрілки генераторів були переглянуті на двох засіданнях ES7 вересня 2016 року [1] [2] . Після обговорення плюсів і мінусів різних синтаксисів (головним чином =*>і =>*) та відсутності обґрунтування та використання випадків для цієї функції вони дійшли висновку, що:

  • Комітет має певний інтерес, але стурбований тим, що функція не тягне ваги для додавання нового фрагмента синтаксису
  • Плануйте переглянути 3 день, щоб побачити, чи зможемо ми =>*хоча б дійти до етапу 0, як частина пропозиції про асинхронізацію [Доменик Денікола]

Пропозиція про генераторні стріли була перенесена на етап 1, де Брендан Ейх і Доменік Денікола були чемпіонами. Згадана вище асинхронна ітерація була завершена та впроваджена у 2018 році.

У жовтні 2019 року з'явилося офіційне репо від Сергія Рубанова з більшою дискусією про синтаксис та інші деталі.


8

У мене теж було те саме питання і я прийшов сюди. Прочитавши публікації та коментарі, я відчув, що використання генератора у функції стрілки здається невиразним:

const generator = () => 2*3; // * implies multiplication
// so, this would be a confusing
const generator = () =>* something; // err, multiplying?
const generator = () =*> ... // err, ^^
const generator = ()*=> ... // err, *=3, still multiplying?
const generator=*()=> ... // err, ^^
const generator = *param => ... //err, "param" is not fixed word

Це може бути основною причиною того, що вони не застосували генератор стосовно функції стрілки.


Але, якби я був одним із них, я міг би подумати так:

const generator = gen param => ... // hmm, gen indicates a generator
const generator = gen () => ... // ^^

Це відчувається так, як ми маємо асинхронну функцію:

const asyncFunction = async () => ... // pretty cool

Тому що при нормальній функції ключове слово async існує, тому функція стрілки використовує його - async () =>швидше за все, здається async function().

Але, немає ключових слів , як genі generatorна жаль стрілка функція не використовує його.

Щоб зробити висновок:

Навіть якщо вони хочуть реалізувати генератор у функції стрілки, я думаю, що їм потрібно переосмислити синтаксис генератора в ядрі js:

generator function myfunc() {}
// rather than
function* myfunc() {} // or, function *myfunc() {}

І це буде великою помилкою. Отже, утримувати функцію стрілки від генератора, це досить здорово.


Після коментаря @Bergi :

Ні. Функції стрілок повинні бути легкими (та не мають, наприклад, прототипу) і часто однолінійними, тоді як генератори - навпаки.

Я скажу, що ціль генератора, який слід використовувати, - це запуск-стоп-біг, і тому я не думаю, що нам потрібно дбати про прототип, про лексичне це і т.д.


2
Також можна розглянути екзотичні варіанти () ~> { yield 'a'; yield 'b'; }. Якщо чесно, я просто люблю тильди.
Гершом

@Gershom Ось так мови програмування, як Perl, йдуть зовсім не так
Sapphire_Brick

2

Я знаю, що це дуже пізно, але іншою можливою причиною може бути синтаксис. можливо, (*() => {})працює, але як бути (9 ** () => {})? Це 9, що повертається до сили функції стрілки NaN, або повертається у 9 разів функція стрілки генератора NaN? Це можна зробити за допомогою альтернативного синтаксису, як, =>*як це було сказано в іншій відповіді, але, можливо, виникло бажання зберегти узгодженість синтаксису функції генератора (наприклад, function* () {}і { *genMethod() {} }) під час його реалізації. Не надто виправдання, але причина для цього.


1
: +1: для подвійних зірочок ... Старий хлопець JS тут. Хто каже, що ви не можете навчити старого собаку нових хитрощів: радість:
Shanimal

Єдина причина, чому вони цього не роблять, це тому, що зробити синтаксичний аналіз важко. Це цілком можливо і не вимагає компромісів у синтаксисі.
Джейсон МакКаррелл

@JasonMcCarrell Якщо б вони піклувалися про те, щоб зробити парсер не надто складним, то, можливо, Брендан Ейч мав би поставити схему у браузері.
Sapphire_Brick

1

Зараз ви цього не можете, але в майбутньому це може бути тому, що пропозиція TC39 щодо випуску цього ж року відбудеться в жовтні 2019 року, що знаходиться на етапі 1.


-4

Існує приємний спосіб вирішення редукс-саги

import { call, all } from 'redux-saga/effects';

function* gen() {
   yield all([].map(() => {
      return call(....);
   }));
}

4
Як ми знаємо, що ОП використовує Redux?
Марос
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.