From 074785cea106179cb3305637055ab0a009ca74f2 Mon Sep 17 00:00:00 2001 From: Peter Bengtsson Date: Tue, 8 Dec 2020 14:42:52 -0500 Subject: initial commit --- .../operators/generator_comprehensions/index.html | 229 +++++++++++++++++++++ 1 file changed, 229 insertions(+) create mode 100644 files/ru/web/javascript/reference/operators/generator_comprehensions/index.html (limited to 'files/ru/web/javascript/reference/operators/generator_comprehensions') diff --git a/files/ru/web/javascript/reference/operators/generator_comprehensions/index.html b/files/ru/web/javascript/reference/operators/generator_comprehensions/index.html new file mode 100644 index 0000000000..fb04526d8a --- /dev/null +++ b/files/ru/web/javascript/reference/operators/generator_comprehensions/index.html @@ -0,0 +1,229 @@ +--- +title: Упрощенный синтаксис создания функций-генераторов +slug: Web/JavaScript/Reference/Operators/Generator_comprehensions +tags: + - Итераторы +translation_of: Archive/Web/JavaScript/Generator_comprehensions +--- +
Не в стандарте. Не используйте!
+Включения генераторов - нестандартная возможность, и вряд ли когда-либо появится в ECMAScript. В будущем попробуйте использовать {{jsxref("Statements/function*", "generator", "", 1)}}.
+ +
{{jsSidebar("Operators")}}
+ +
Синтаксис включений генераторов - это выражение, которое позволяет быстро создать новую функцию-генератор из существующего итератора. Включения присутствуют во множестве языков программирования.
+ +
 
+ +
Ниже показаны отличия от старого синтаксиса генераторных выражений в SpiderMonkey, основанных на предложениях к стандарту ECMAScript 4.
+ +
 
+ +

Синтаксис

+ +
(for (x of iterable) x)
+(for (x of iterable) if (condition) x)
+(for (x of iterable) for (y of iterable) x + y)
+
+ +

Описание

+ +

Внутри включений генераторов допустимы два типа компонентов:

+ + + +

Конструкция for-of всегда идёт первой. Таких конструкций может быть несколько.

+ +

Существенный недостаток {{jsxref("Operators/Array_comprehensions","включений массивов","","true")}} - это то, что они создают полносью новый массив в памяти. Даже когда исходный массив небольшой, накладные расходы получаются весьма заметными, а уж когда входные данные - это большой массив или дорогой (или бесконечный) генератор, создание нового массива может быть трудной задачей.

+ +

Генераторы позволяют выполнять ленивые вычисления последовательностей, то есть рассчитывать данные только тогда, когда они нужны. Синтаксисы включений генераторов и включений массивов практически аналогичны — первые используют () вместо [] — но вместо массива они создают генератор, который может выполняться лениво. Включения генераторов можно считать просто более кратким способом создания генераторов.

+ +

Предположим, у нас есть итератор it, который итерирует по длинной последовательности чисел. Мы хотим создать новый итератор, который будет итерировать по тем же числам, умноженным на два. Включение массивов создало бы в памяти новый массив с умноженными числами:

+ +
var doubles = [for (i in it) i * 2];
+
+ +

А включение генераторов создало бы новый итератор, который высчитывал бы  следующее умноженное значение, когда оно нужно:

+ +
var it2 = (for (i in it) i * 2);
+console.log(it2.next()); // Первое значение из it, умноженное на два
+console.log(it2.next()); // Второе значение из it, умноженное на два
+
+ +

Когда включение генераторов передаётся как аргумент функции, можно обойтись без скобок вокруг включения:

+ +
var result = doSomething(for (i in it) i * 2);
+
+ +

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

+ +

Примеры

+ +

Простое включение генераторов

+ +
(for (i of [ 1, 2, 3 ]) i*i );
+// Функция-генератор, которая отдаёт 1, 4, 9 и так далее
+
+[...(for (i of [ 1, 2, 3 ]) i*i )];
+// [1, 4, 9]
+
+var abc = [ "A", "B", "C" ];
+(for (letters of abc) letters.toLowerCase());
+// Функция-генератор, которая отдаёт 'a', 'b' и 'c'
+
+ +

Включение генераторов с условием

+ +
var years = [ 1954, 1974, 1990, 2006, 2010, 2014 ];
+
+(for (year of years) if (year > 2000) year);
+// функция-генератор, которая отдаёт 2006, 2010 и 2014
+
+(for (year of years) if (year > 2000) if(year < 2010) year);
+// функция-генератор, которая отдаёт 2006, как и функция ниже:
+
+(for (year of years) if (year > 2000 && year < 2010) year);
+// функция-генератор, которая отдаёт 2006
+
+ +

Включение генератора в сравнении с функцией-генератором

+ +

Будет проще понять синтаксис включений генераторов, если сравнить его с функцией-генератором.

+ +

Пример 1: Простой генератор.

+ +
var numbers = [ 1, 2, 3 ];
+
+// Функция-генератор
+(function*() {
+  for (let i of numbers) {
+    yield i * i;
+  }
+})()
+
+// Включение генератора
+(for (i of numbers) i*i );
+
+// Результат: в обоих случаях получается генератор, который отдаёт [ 1, 4, 9 ]
+
+ +

Пример 2: Использование if в генераторе.

+ +
var numbers = [ 1, 2, 3 ];
+
+// Функция-генератор
+(function*() {
+  for (let i of numbers) {
+    if (i < 3) {
+      yield i * 1;
+    }
+  }
+})()
+
+// Включение генератора
+(for (i of numbers) if (i < 3) i);
+
+// Результат: в обоих случаях получается генератор, который отдаёт [ 1, 2 ]
+ +

Спецификации

+ +

Включения генераторов изначально входили в черновик ECMAScript 6, но их убрали в ревизии 27 (August 2014). Please see older revisions of ES6 for specification semantics.

+ +

Поддержка браузерами

+ +

{{CompatibilityTable}}

+ +
+ + + + + + + + + + + + + + + + + + + +
FeatureChromeFirefox (Gecko)Internet ExplorerOperaSafari
Начальная поддержка{{CompatNo}}{{ CompatGeckoDesktop("30") }}{{CompatNo}}{{CompatNo}}{{CompatNo}}
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
FeatureAndroidChrome for AndroidFirefox Mobile (Gecko)IE MobileOpera MobileSafari Mobile
Начальная поддержка{{CompatNo}}{{CompatNo}}{{ CompatGeckoMobile("30") }}{{CompatNo}}{{CompatNo}}{{CompatNo}}
+
+ +

Особенности реализации в SpiderMonkey

+ + + +

Отличия от старых JS1.7/JS1.8 включений

+ +
JS1.7/JS1.8 включения убраны из Gecko 46 ({{bug(1220564)}}).
+ +

Старый синтаксис включений (не используйте!):

+ +
(X for (Y in Z))
+(X for each (Y in Z))
+(X for (Y of Z))
+
+ +

Отличия:

+ + + +

См. также

+ + -- cgit v1.2.3-54-g00ecf