aboutsummaryrefslogtreecommitdiff
path: root/files/ru/web/javascript/reference/operators/generator_comprehensions
diff options
context:
space:
mode:
authorPeter Bengtsson <mail@peterbe.com>2020-12-08 14:42:52 -0500
committerPeter Bengtsson <mail@peterbe.com>2020-12-08 14:42:52 -0500
commit074785cea106179cb3305637055ab0a009ca74f2 (patch)
treee6ae371cccd642aa2b67f39752a2cdf1fd4eb040 /files/ru/web/javascript/reference/operators/generator_comprehensions
parentda78a9e329e272dedb2400b79a3bdeebff387d47 (diff)
downloadtranslated-content-074785cea106179cb3305637055ab0a009ca74f2.tar.gz
translated-content-074785cea106179cb3305637055ab0a009ca74f2.tar.bz2
translated-content-074785cea106179cb3305637055ab0a009ca74f2.zip
initial commit
Diffstat (limited to 'files/ru/web/javascript/reference/operators/generator_comprehensions')
-rw-r--r--files/ru/web/javascript/reference/operators/generator_comprehensions/index.html229
1 files changed, 229 insertions, 0 deletions
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
+---
+<div class="warning"><strong>Не в стандарте. Не используйте!</strong><br>
+Включения генераторов - нестандартная возможность, и вряд ли когда-либо появится в ECMAScript. В будущем попробуйте использовать {{jsxref("Statements/function*", "generator", "", 1)}}.</div>
+
+<div>{{jsSidebar("Operators")}}</div>
+
+<div>Синтаксис <strong>включений генераторов </strong>- это выражение, которое позволяет быстро создать новую функцию-генератор из существующего итератора. Включения присутствуют во множестве языков программирования.</div>
+
+<div> </div>
+
+<div><a href="https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Operators/Generator_comprehensions#Differences_to_the_older_JS1.7.2FJS1.8_comprehensions">Ниже</a> показаны отличия от старого синтаксиса генераторных выражений в SpiderMonkey, основанных на предложениях к стандарту ECMAScript 4.</div>
+
+<div> </div>
+
+<h2 id="Синтаксис">Синтаксис</h2>
+
+<pre class="syntaxbox">(for (x of iterable) x)
+(for (x of iterable) if (condition) x)
+(for (x of iterable) for (y of iterable) x + y)
+</pre>
+
+<h2 id="Описание">Описание</h2>
+
+<p>Внутри включений генераторов допустимы два типа компонентов:</p>
+
+<ul>
+ <li>{{jsxref("Statements/for...of", "for...of")}} и</li>
+ <li>{{jsxref("Statements/if...else", "if")}}</li>
+</ul>
+
+<p>Конструкция <code>for-of</code> всегда идёт первой. Таких конструкций может быть несколько.</p>
+
+<p>Существенный недостаток {{jsxref("Operators/Array_comprehensions","включений массивов","","true")}} - это то, что они создают полносью новый массив в памяти. Даже когда исходный массив небольшой, накладные расходы получаются весьма заметными, а уж когда входные данные - это большой массив или дорогой (или бесконечный) генератор, создание нового массива может быть трудной задачей.</p>
+
+<p>Генераторы позволяют выполнять ленивые вычисления последовательностей, то есть рассчитывать данные только тогда, когда они нужны. Синтаксисы включений генераторов и включений массивов практически аналогичны — первые используют () вместо [] — но вместо массива они создают генератор, который может выполняться лениво. Включения генераторов можно считать просто более кратким способом создания генераторов.</p>
+
+<p>Предположим, у нас есть итератор <code>it</code>, который итерирует по длинной последовательности чисел. Мы хотим создать новый итератор, который будет итерировать по тем же числам, умноженным на два. Включение массивов создало бы в памяти новый массив с умноженными числами:</p>
+
+<pre class="brush: js">var doubles = [for (i in it) i * 2];
+</pre>
+
+<p>А включение генераторов создало бы новый итератор, который высчитывал бы  следующее умноженное значение, когда оно нужно:</p>
+
+<pre class="brush: js">var it2 = (for (i in it) i * 2);
+console.log(it2.next()); // Первое значение из it, умноженное на два
+console.log(it2.next()); // Второе значение из it, умноженное на два
+</pre>
+
+<p>Когда включение генераторов передаётся как аргумент функции, можно обойтись без скобок вокруг включения:</p>
+
+<pre class="brush: js">var result = doSomething(for (i in it) i * 2);
+</pre>
+
+<p>Эти два примера отличаются тем, что используя включения генераторов, нам нужно пройтись по структуре объекта только однажды, а используя включения массивов - дважды: сначала при создании включения, затем, при самой итерации.</p>
+
+<h2 id="Примеры">Примеры</h2>
+
+<h3 id="Простое_включение_генераторов">Простое включение генераторов</h3>
+
+<pre class="brush:js">(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'
+</pre>
+
+<h3 id="Включение_генераторов_с_условием">Включение генераторов с условием</h3>
+
+<pre class="brush: js">var years = [ 1954, 1974, 1990, 2006, 2010, 2014 ];
+
+(for (year of years) if (year &gt; 2000) year);
+// функция-генератор, которая отдаёт 2006, 2010 и 2014
+
+(for (year of years) if (year &gt; 2000) if(year &lt; 2010) year);
+// функция-генератор, которая отдаёт 2006, как и функция ниже:
+
+(for (year of years) if (year &gt; 2000 &amp;&amp; year &lt; 2010) year);
+// функция-генератор, которая отдаёт 2006
+</pre>
+
+<h3 id="Включение_генератора_в_сравнении_с_функцией-генератором">Включение генератора в сравнении с функцией-генератором</h3>
+
+<p>Будет проще понять синтаксис включений генераторов, если сравнить его с функцией-генератором.</p>
+
+<p>Пример 1: Простой генератор.</p>
+
+<pre class="brush: js">var numbers = [ 1, 2, 3 ];
+
+// Функция-генератор
+(function*() {
+ for (let i of numbers) {
+ yield i * i;
+ }
+})()
+
+// Включение генератора
+(for (i of numbers) i*i );
+
+// Результат: в обоих случаях получается генератор, который отдаёт [ 1, 4, 9 ]
+</pre>
+
+<p>Пример 2: Использование <code>if</code> в генераторе.</p>
+
+<pre class="brush: js">var numbers = [ 1, 2, 3 ];
+
+// Функция-генератор
+(function*() {
+ for (let i of numbers) {
+ if (i &lt; 3) {
+ yield i * 1;
+ }
+ }
+})()
+
+// Включение генератора
+(for (i of numbers) if (i &lt; 3) i);
+
+// Результат: в обоих случаях получается генератор, который отдаёт [ 1, 2 ]</pre>
+
+<h2 id="Спецификации">Спецификации</h2>
+
+<p>Включения генераторов изначально входили в черновик ECMAScript 6, но их убрали в ревизии 27 (August 2014). Please see older revisions of ES6 for specification semantics.</p>
+
+<h2 id="Поддержка_браузерами">Поддержка браузерами</h2>
+
+<p>{{CompatibilityTable}}</p>
+
+<div id="compat-desktop">
+<table class="compat-table">
+ <tbody>
+ <tr>
+ <th>Feature</th>
+ <th>Chrome</th>
+ <th>Firefox (Gecko)</th>
+ <th>Internet Explorer</th>
+ <th>Opera</th>
+ <th>Safari</th>
+ </tr>
+ <tr>
+ <td>Начальная поддержка</td>
+ <td>{{CompatNo}}</td>
+ <td>{{ CompatGeckoDesktop("30") }}</td>
+ <td>{{CompatNo}}</td>
+ <td>{{CompatNo}}</td>
+ <td>{{CompatNo}}</td>
+ </tr>
+ </tbody>
+</table>
+</div>
+
+<div id="compat-mobile">
+<table class="compat-table">
+ <tbody>
+ <tr>
+ <th>Feature</th>
+ <th>Android</th>
+ <th>Chrome for Android</th>
+ <th>Firefox Mobile (Gecko)</th>
+ <th>IE Mobile</th>
+ <th>Opera Mobile</th>
+ <th>Safari Mobile</th>
+ </tr>
+ <tr>
+ <td>Начальная поддержка</td>
+ <td>{{CompatNo}}</td>
+ <td>{{CompatNo}}</td>
+ <td>{{ CompatGeckoMobile("30") }}</td>
+ <td>{{CompatNo}}</td>
+ <td>{{CompatNo}}</td>
+ <td>{{CompatNo}}</td>
+ </tr>
+ </tbody>
+</table>
+</div>
+
+<h2 id="Особенности_реализации_в_SpiderMonkey">Особенности реализации в SpiderMonkey</h2>
+
+<ul>
+ <li>Нельзя использовать {{jsxref("Statements/let", "let")}}, потому что она доступна только в JS версии 1.7 и тэгах XUL.</li>
+ <li>Деструктуризация во включениях пока не поддерживается ({{bug(980828)}}).</li>
+</ul>
+
+<h2 id="Отличия_от_старых_JS1.7JS1.8_включений">Отличия от старых JS1.7/JS1.8 включений</h2>
+
+<div class="warning">JS1.7/JS1.8 включения убраны из Gecko 46 ({{bug(1220564)}}).</div>
+
+<p><strong>Старый синтаксис включений (не используйте!):</strong></p>
+
+<pre class="brush: js example-bad">(X for (Y in Z))
+(X for each (Y in Z))
+(X for (Y of Z))
+</pre>
+
+<p>Отличия:</p>
+
+<ul>
+ <li>Включения в ES7 создают отдельную область видимость для каждой итерации <code>for</code>, вместо одной области для всего включения:
+
+ <ul>
+ <li>Старые: <code>[...(()=&gt;x for (x of [0, 1, 2]))][1]() // 2</code></li>
+ <li>Новые: <code>[...(for (x of [0, 1, 2]) ()=&gt;x)][1]() // 1, each iteration creates a fresh binding for x. </code></li>
+ </ul>
+ </li>
+ <li>Включения в ES7 начинаются с <code>for</code> вместо выражения присваивания:
+ <ul>
+ <li>Старые: <code>(i * 2 for (i of numbers))</code></li>
+ <li>Новые: <code>(for (i of numbers) i * 2)</code></li>
+ </ul>
+ </li>
+ <li>Включения в ES7 могут содержать несколько <code>if</code>  и  <code>for</code>.</li>
+ <li>Включения в ES7 работают только с итерациями <code>{{jsxref("Statements/for...of", "for...of")}}</code>, но не с <code>{{jsxref("Statements/for...in", "for...in")}}</code></li>
+</ul>
+
+<h2 id="См._также">См. также</h2>
+
+<ul>
+ <li>{{jsxref("Statements/for...of", "for...of")}}</li>
+ <li>{{jsxref("Operators/Array_comprehensions", "Array comprehensions")}}</li>
+</ul>