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/functions/arrow_functions/index.html | |
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/functions/arrow_functions/index.html')
-rw-r--r-- | files/ru/web/javascript/reference/functions/arrow_functions/index.html | 378 |
1 files changed, 378 insertions, 0 deletions
diff --git a/files/ru/web/javascript/reference/functions/arrow_functions/index.html b/files/ru/web/javascript/reference/functions/arrow_functions/index.html new file mode 100644 index 0000000000..b903c96852 --- /dev/null +++ b/files/ru/web/javascript/reference/functions/arrow_functions/index.html @@ -0,0 +1,378 @@ +--- +title: Стрелочные функции +slug: Web/JavaScript/Reference/Functions/Arrow_functions +tags: + - ECMAScript6 + - JavaScript + - Функции +translation_of: Web/JavaScript/Reference/Functions/Arrow_functions +--- +<div>{{jsSidebar("Functions")}}</div> + +<h2 id="Сводка">Сводка</h2> + +<p><strong>Выражения стрелочных функций</strong> имеют более короткий синтаксис по сравнению с <a href="/ru/docs/Web/JavaScript/Reference/Operators/function">функциональными выражениями</a> и лексически привязаны к значению <a href="/ru/docs/Web/JavaScript/Reference/Operators/this">this</a> (но не привязаны к собственному <a href="/ru/docs/Web/JavaScript/Reference/Operators/this">this</a>, <a href="https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Functions/arguments">arguments</a>, <a href="https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Operators/super">super</a>, или <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new.target">new.target</a>). Выражение стрелочных функций не позволяют задавать имя, поэтому стрелочные функции <a href="/ru/docs/Web/JavaScript/Reference/Global_Objects/Function/name">анонимны</a>, если их ни к чему не присвоить.</p> + +<h2 id="Syntax" name="Syntax">Синтаксис</h2> + +<h3 id="Базовый_синтаксис">Базовый синтаксис</h3> + +<pre class="brush: js">(param1, param2, …, paramN) => { statements } +(param1, param2, …, paramN) => expression +// эквивалентно: (param1, param2, …, paramN) => { return expression; } + +// Круглые скобки не обязательны для единственного параметра: +(singleParam) => { statements } +singleParam => { statements } + +// Функция без параметров нуждается в круглых скобках: +() => { statements } +() => expression +// Эквивалентно: () => { return expression; } +</pre> + +<h3 id="Расширенный_синтаксис">Расширенный синтаксис</h3> + +<pre class="brush: js">// Когда возвращаете литеральное выражение объекта, заключите тело в скобки +params => ({foo: bar}) + +// <a href="https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Functions/Rest_parameters">Rest параметры</a> и <a href="https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Functions/Default_parameters">параметры по умолчанию</a> поддерживаются +(param1, param2, ...rest) => { statements } +(param1 = defaultValue1, param2, …, paramN = defaultValueN) => { statements } + +// <a href="https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment">Деструктуризация</a> тоже поддерживается +var f = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c; +f(); // 6 +</pre> + +<p>Подробные примеры синтаксиса можно посмотреть <a href="http://wiki.ecmascript.org/doku.php?id=harmony:arrow_function_syntax" title="http://wiki.ecmascript.org/doku.php?id=harmony:arrow_function_syntax">здесь</a>.</p> + +<h2 id="Описание">Описание</h2> + +<p>Смотрите также <a href="https://hacks.mozilla.org/2015/06/es6-in-depth-arrow-functions/">"ES6 In Depth: Arrow functions" on hacks.mozilla.org</a>.</p> + +<p>Два фактора повлияли на появление стрелочных функции: более короткий синтаксис и лексика <code>this</code>.</p> + +<h3 id="Короткие_функции">Короткие функции</h3> + +<p>В некоторых функциональных шаблонах приветствуются более короткие функции. Сравните:</p> + +<pre class="brush: js">var elements = [ + 'Hydrogen', + 'Helium', + 'Lithium', + 'Beryllium' +]; + +elements.map(function(element) { + return element.length; +}); // Это выражение вернет массив [8, 6, 7, 9] + +// Функцию выше можно записать как стрелочную функцию: +elements.map((element) => { + return element.length; +}); // [8, 6, 7, 9] + +// Если единственным оператором в выражении стрелочной функции является return, +// можно удалить return и окружающие фигурные скобки + +elements.map(element => element.length); // [8, 6, 7, 9] + +// В данном случае, поскольку нам нужно только свойство length, мы можем использовать деструктуризированный параметр: +// Обратите внимание, что строка `"length"` соответствует свойству, которое мы хотим получить, +// в то время как `lengthFooBArX` это просто имя переменной, которую можно назвать как вы хотите +elements.map(({ "length": lengthFooBArX }) => lengthFooBArX); // [8, 6, 7, 9] + +// Это задание деструктуризированного параметра может быть записано, как показано ниже. Тем не менее, обратите внимание, +// что нет строки `"length"`, чтобы выбрать, какое свойство мы хотим получить. Вместо этого в качестве свойства, +// которое мы хотим извлечь из объекта, используется само литеральное имя переменной `length` +elements.map(({ length }) => length); // [8, 6, 7, 9] +</pre> + +<h3 id="Отсутствие_связывания_с_this">Отсутствие связывания с <code>this</code></h3> + +<p>До появления стрелочных функций, каждая новая функция имела своё значение <code><a href="/ru/docs/Web/JavaScript/Reference/Operators/this">this</a></code> (новый объект в случае конструктора, undefined в <a href="/ru/docs/Web/JavaScript/Reference/Strict_mode">strict</a> режиме вызова функции, контекст объекта при вызове функции как "метода объекта" и т.д.). Это очень раздражало при использовании объектно-ориентированного стиля программирования.</p> + +<pre class="brush: js">function Person() { + // В конструкторе Person() `this` указывает на себя. + this.age = 0; + + setInterval(function growUp() { + // В нестрогом режиме, в функции growUp() `this` указывает + // на глобальный объект, который отличается от `this`, + // определяемом в конструкторе Person(). + this.age++; + }, 1000); +} + +var p = new Person(); +</pre> + +<p>В ECMAScript 3/5, данная проблема решалась присваиванием значения <code>this</code> переменной:</p> + +<pre class="brush: js">function Person() { + var that = this; + that.age = 0; + + setInterval(function growUp() { + // Функция с обратным вызовом(<a href="/en-US/docs/Mozilla/js-ctypes/Using_js-ctypes/Declaring_and_Using_Callbacks">callback</a>) содержит переменную that, которая + // ссылается на требуемый объект this. + that.age++; + }, 1000); +}</pre> + +<p>Кроме этого, может быть создана <a href="/ru/docs/Web/JavaScript/Reference/Global_Objects/Function/bind">привязанная функция</a>, в которую передаётся требуемое значение <code><a href="/ru/docs/Web/JavaScript/Reference/Operators/this">this</a></code> для функции (функция <code>growUp()</code> в примере выше).</p> + +<p>Стрелочные функции не содержат собственный контекст <code><a href="/ru/docs/Web/JavaScript/Reference/Operators/this">this</a></code>, а используют значение <code><a href="/ru/docs/Web/JavaScript/Reference/Operators/this">this</a></code> окружающего контекста. Поэтому нижеприведенный код работает как предполагалось:</p> + +<pre class="brush: js">function Person(){ + this.age = 0; + + setInterval(() => { + this.age++; // `this` указывает на объект Person + }, 1000); +} + +var p = new Person();</pre> + +<h4 id="Строгий_режим_исполнения">Строгий режим исполнения</h4> + +<p>Поскольку значение <code>this</code> определяется лексикой, правила строгого режима (<a href="/ru/docs/Web/JavaScript/Reference/Strict_mode">strict mode</a>) относительно <code>this</code> игнорируются:</p> + +<pre class="brush: js">var f = () => { 'use strict'; return this; }; +f() === window; // или глобальный объект</pre> + +<p>Все остальные правила строгого режима применяются как обычно.</p> + +<h4 id="Вызов_с_помощью_call_или_apply">Вызов с помощью call или apply</h4> + +<p>Так как значение <code>this</code> определяется лексикой, вызов стрелочных функций с помощью методов <code>call()</code> или <code>apply()</code>, даже если передать аргументы в эти методы, не влияет на значение <code>this</code>:</p> + +<pre class="brush: js">var adder = { + base : 1, + + add : function(a) { + var f = v => v + this.base; + return f(a); + }, + + addThruCall: function(a) { + var f = v => v + this.base; + var b = { + base : 2 + }; + + return f.call(b, a); + } +}; + +console.log(adder.add(1)); // Выводит 2 +console.log(adder.addThruCall(1)); // Всё равно выводит 2 +</pre> + +<h3 id="Не_имеет_собственного_объекта_arguments">Не имеет собственного объекта arguments</h3> + +<p>Стрелочные функции не имеют собственного объекта arguments, поэтому в теле стрелочных функций arguments будет ссылаться на переменную в окружающей области.</p> + +<pre class="brush: js">var arguments = 42; +var arr = () => arguments; + +arr(); // 42 + +function foo() { + var f = (i) => arguments[0] + i; // Неявное связывание ссылки arguments + // стрелочной функции f + // c объектом arguments функции foo + return f(2); +} + +foo(1); // 3</pre> + +<p>В большинстве случаев лучшей заменой объекта arguments в стрелочных функциях являются <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters">rest параметры</a>:</p> + +<pre class="brush: js">function foo() { + var f = (...args) => args[0]; + return f(2); +} + +foo(1); // 2 +</pre> + +<h3 id="Использование_стрелочных_функций_как_методов">Использование стрелочных функций как методов</h3> + +<p>Как показано ранее, стрелочные функции лучше всего подходят для функций без методов. Посмотрим, что будет, когда мы попробуем их использовать как методы:</p> + +<pre class="brush: js">'use strict'; +var obj = { + i: 10, + b: () => console.log(this.i, this), + c: function() { + console.log(this.i, this); + } +} +obj.b(); // prints undefined, Window {...} (или глобальный объект) +obj.c(); // prints 10, Object {...} +</pre> + +<p>Стрелочные функции не объявляют привязку ("bind") их контекста <code>this</code>. Другой пример включает {{jsxref("Object.defineProperty()")}}:</p> + +<pre class="brush: js">'use strict'; +var obj = { + a: 10 +}; + +Object.defineProperty(obj, 'b', { + get: () => { + console.log(this.a, typeof this.a, this); + return this.a + 10; + // представляет глобальный объект 'Window', но 'this.a' возвращает 'undefined' + } +});</pre> + +<h3 id="Использование_оператора_new">Использование оператора <code>new</code></h3> + +<p>Стрелочные функции не могут быть использованы как конструктор и вызовут ошибку при использовании с <code>new</code>:</p> + +<pre class="brush: js">var a = new (function() {}) +// переменной "a" будет присвоено значение экземпляра анонимной функции + +var b = new (() => {}) +// будет выброшено исключениe +// Uncaught TypeError: (intermediate value) is not a constructor</pre> + +<h3 id="Использование_ключевого_слова_yield">Использование ключевого слова <code>yield</code></h3> + +<p>Ключевое слово <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/yield">yield</a></code> не может быть использовано в теле стрелочной функции (за исключением случаев, когда разрешается использовать в функциях, вложенных в тело стрелочной функции). Как следствие стрелочные функции не могут быть использованы как генераторы.</p> + +<h2 id="Тело_функции">Тело функции</h2> + +<p>Тело стрелочной функции может иметь краткую (concise body) или блочную (block body) форму.</p> + +<p>Блочная форма не возвращает значение, необходимо явно вернуть значение.</p> + +<pre class="brush: js">var func = x => x * x; // краткий синтаксис, + // неявно возвращает результат +var func = (x, y) => { return x + y; }; // блочный синтаксис, + // явно возвращает результат</pre> + +<h2 id="Возвращаемые_объектные_строки_литералы">Возвращаемые объектные строки (литералы)</h2> + +<p>Помните о том, что возвращаемые <a href="/ru/docs/Web/JavaScript/Guide/Grammar_and_types#Литерал_объекта/">объектные строки</a> используют сокращённый синтаксис: <code>params => {object:literal}</code> будет работать не так, как ожидается.</p> + +<pre class="brush: js">var func = () => { foo: 1 }; +// Вызов func() возвращает undefined! + +var func = () => { foo: function() {} }; +// SyntaxError: function statement requires a name</pre> + +<p>Это происходит потому что код в скобках ({}) распознаётся как цепочка выражений (т.е. <code>foo</code> трактуется как наименование, а не как ключ в объектной строке).</p> + +<p>Не забывайте оборачивать скобками объектные строки.</p> + +<pre class="brush: js">var func = () => ({ foo: 1 });</pre> + +<h2 id="Разрывы_строк">Разрывы строк</h2> + +<p>Стрелочная функция не может содержать разрывы строк между параметрами и стрелкой.</p> + +<pre class="brush: js line-numbers language-js">var func = () + => 1; +// SyntaxError: expected expression, got '=>' +</pre> + +<h2 id="Разбор_порядка_следования">Разбор порядка следования</h2> + +<p>Поскольку стрелка в стрелочной функции не является оператором, то стрелочные функции имеют специальные правила разбора (парсинга), которые взаимодействуют с <a href="/ru/docs/Web/JavaScript/Reference/Operators/Operator_Precedence/">приоритетами операторов</a> иначе, чем в обычных функциях.</p> + +<pre class="brush: js">let callback; + +callback = callback || function() {}; // ok + +callback = callback || () => {}; +// SyntaxError: invalid arrow-function arguments + +callback = callback || (() => {}); // ok +</pre> + +<h2 id="Больше_примеров">Больше примеров</h2> + +<pre class="brush: js">// Пустая стрелочная функция возвращает undefined +let empty = () => {}; + +(() => 'foobar')(); +// Вернёт "foobar" +// (Это Immediately Invoked Function Expression +// смотри '<a href="https://developer.mozilla.org/ru/docs/%D0%A1%D0%BB%D0%BE%D0%B2%D0%B0%D1%80%D1%8C/IIFE">IIFE</a>' в справочнике) + +var simple = a => a > 15 ? 15 : a; +simple(16); // 15 +simple(10); // 10 + +let max = (a, b) => a > b ? a : b; + +// Удобные операции над массивами: filter, map, ... + +var arr = [5, 6, 13, 0, 1, 18, 23]; + +var sum = arr.reduce((a, b) => a + b); +// 66 + +var even = arr.filter(v => v % 2 == 0); +// [6, 0, 18] + +var double = arr.map(v => v * 2); +// [10, 12, 26, 0, 2, 36, 46] + +// Более короткие цепочки promise-ов +promise.then(a => { + // ... +}).then(b => { + // ... +}); + +// Стрелочные функции без параметров, которые визуально легче разбирать +setTimeout( () => { + console.log('Я буду раньше'); + setTimeout( () => { + // deeper code + console.log('Я буду позже'); + }, 1); +}, 1); +</pre> + +<h2 id="Спецификации">Спецификации</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Спецификация</th> + <th scope="col">Статус</th> + <th scope="col">Комментарий</th> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-arrow-function-definitions', 'Arrow Function Definitions')}}</td> + <td>{{Spec2('ES6')}}</td> + <td>Изначальное определение.</td> + </tr> + </tbody> +</table> + +<h2 id="Совместимость_с_браузерами">Совместимость с браузерами</h2> + + + +<p>{{Compat("javascript.functions.arrow_functions")}}</p> + +<h3 id="Замечания_для_Firefox">Замечания для Firefox</h3> + +<ul> + <li>Первоначальная реализация стрелочных функций в Firefox автоматически переводила их в строгий режим. Это поведение было изменено в <a href="/en-US/docs/Mozilla/Firefox/Releases/24" title="/en-US/docs/Mozilla/Firefox/Releases/24">Firefox 24</a>. Использование <code>"use strict";</code> стало обязательным.</li> + <li>Стрелочные функции семантически отличаются от нестандартных <a href="/ru/docs/Web/JavaScript/Reference/Operators/Expression_closures">Expression Closures</a>, добавленных в <a href="/en-US/Firefox/Releases/3">Firefox 3</a> (подробности в <a href="/en-US/docs/Web/JavaScript/New_in_JavaScript/1.8">Javascript 1.8</a>); в Expression Closures значение <code>this</code> не привязано лексически.</li> + <li>До <a href="https://developer.mozilla.org/en-US/Firefox/Releases/39">Firefox 39</a>, перенос строки (<code>\n</code>) был ошибочно разрешён после аргументов стрелочной функции. Это было исправлено для соблюдения спецификации ES2015, и код вроде: <code>() \n => {}</code> теперь вызывает {{jsxref("SyntaxError")}} в этой и более поздних версиях.</li> +</ul> + +<h2 id="See_also">See also</h2> + +<ul> + <li><a href="https://hacks.mozilla.org/2015/06/es6-in-depth-arrow-functions/">"ES6 In Depth: Arrow functions" on hacks.mozilla.org</a></li> +</ul> |