diff options
| author | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:42:52 -0500 |
|---|---|---|
| committer | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:42:52 -0500 |
| commit | 074785cea106179cb3305637055ab0a009ca74f2 (patch) | |
| tree | e6ae371cccd642aa2b67f39752a2cdf1fd4eb040 /files/ru/web/javascript/reference/operators/generator_comprehensions | |
| parent | da78a9e329e272dedb2400b79a3bdeebff387d47 (diff) | |
| download | translated-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.html | 229 |
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 > 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 +</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 < 3) { + yield i * 1; + } + } +})() + +// Включение генератора +(for (i of numbers) if (i < 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>[...(()=>x for (x of [0, 1, 2]))][1]() // 2</code></li> + <li>Новые: <code>[...(for (x of [0, 1, 2]) ()=>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> |
