Стрілецькі функції. Стрілецькі функції в ES6
- Переклад
“Товсті” стрілочні функції (=>), також відомі, як arrow функції – абсолютно нова функціональність у ECMAScript 2015 (раніше відомому під ім'ям ES6). Якщо вірити чуткам, то ECMAScript 2015 => синтаксис став використовуватися замість –> синтаксису під впливом CoffeeScript . Також, не останню роль зіграла схожість передачі контексту цього.
У стрілочних функцій є дві основні завдання: забезпечити більш короткий синтаксис; забезпечити передачу лексичного цього з батьківським scope. Давайте детально розглянемо кожну із них!
Новий синтаксис функцій Класичний синтаксис функцій JavaScript відрізняється ригідністю, будь то функція з однією змінною або сторінка з безліччю функцій. При кожному оголошенні функції вам необхідно писати function () (). Потреба більш лаконічному синтаксисі функцій була однією з причин, чому свого часу CoffeeScript став дуже популярним. Ця потреба особливо очевидна у випадку з невеликими callback функціями. Давайте просто поглянемо на ланцюжок Promise:function getVerifiedToken(selector) ( return getUsers(selector) .then(function (users) ( return users; )) .then(verifyUser) .then(function (user, verifiedToken) ( return verifiedToken; )) .catch(function (err ) (log(err.stack); ));
Вгорі ви бачите більш менш зручно код, написаний з використанням класичного синтаксису function в JavaScript. А ось так виглядає той же код, переписаний з використанням стрілочного синтаксису:
function getVerifiedToken(selector) ( return getUsers(selector) .then(users => users) .then(verifyUser) .then((user, verifiedToken) => verifiedToken) .catch(err => log(err.stack)); )
Тут треба звернути увагу на кілька важливих моментів:
- Ми втратили функцію і (), тому що наші callback функції записуються в один рядок.
- Ми прибрали (). Тепер вони не обгортають список аргументів, коли є лише один аргумент (інші аргументи проходять як винятки; наприклад, (...args) => ...).
- Ми позбулися ключового слова return. Забираючи (), ми дозволяємо однорядковим стрілочним функціям провести неявне повернення (іншими мовами такі функції часто називають лямбда функціями).
const getVerifiedToken = selector => ( return getUsers() .then(users => users) .then(verifyUser) .then((user, verifiedToken) => verifiedToken) .catch(err => log(err.stack)); )
Тут починається найцікавіше. Оскільки наша функція має лише один оператор, ми можемо прибрати (), і код буде дуже схожий на синтаксис CoffeeScript :
const getVerifiedToken = selector => getUsers() .then(users => users) .then(verifyUser) .then((user, verifiedToken) => verifiedToken) .catch(err => log(err.stack));
І все ж таки код вище написаний з використанням синтаксису ES2015. (Я теж здивувався, що він чудово скомпілювався.) Коли ми говоримо про стрілочні функції з одним оператором, це не означає, що оператор не може займати більше одного рядка, для зручності використання.
Є, однак, один істотний мінус: прибравши () зі стрілочних функцій, як ми можемо повернути порожній об'єкт? Наприклад, той самий ()?
const emptyObject = () => (); emptyObject(); //?
А ось як виглядає весь код разом:
function () ( return 1; ) () => ( return 1; ) () => 1 function (a) ( return a * 2; ) (a) => ( return a * 2; ) (a) => a * 2 a => a * 2 function (a, b) ( return a * b; ) (a, b) => ( return a * b; ) (a, b) => a * b function () ( return arguments; ) (...args) => args () => () // undefined () => (()) // ()
$(".current-time").each(function () ( setInterval(function () ( $(this).text(Date.now()); ), 1000); ));
При спробі послатися на цей DOM елемент, заданий через each в callback'е setInterval, ми, на жаль, отримуємо зовсім інший this, - той, який належить callback. Обійти цей момент можна, задавши змінну that або self:
$(".current-time").each(function () ( var self = this; setInterval(function () ( $(self).text(Date.now()); ), 1000); ));
“Товсті” стрілочні функції можуть допомогти вирішити цю проблему, тому що вони не мають цього:
$(".current-time").each(function () ( setInterval(() => $(this).text(Date.now()), 1000); )); Як щодо аргументів? Одним із мінусів стрілочних функцій є те, що у них немає власної змінної arguments, як у звичайних функцій:
function log(msg) ( const print = () => console.log(arguments); print(`LOG: $(msg)`); ) log("hello"); // hello
Повторимося, що у стрілочних функцій немає цих і немає arguments. Однак, взявши це до уваги, ви все ж таки можете отримати аргументи, передані в стрілочні функції за допомогою rest-параметрів (так само відомі, як spread оператори):
function log(msg) ( const print = (...args) => console.log(args); print(`LOG: $(msg)`); ) log("hello"); // LOG: hello Як щодо генераторів? "Товсті" стрілочні функції не можуть використовуватися як генератори. Жодних винятків та обхідних шляхів немає. Висновок “Товсті” стрілочні функції – одна з причин, чому я так люблю JavaScript. Дуже спокусливо просто почати використовувати => замість function. Я бачив цілі бібліотеки, де використовується лише варіант =>. Не думаю, однак, що це розумно. Зрештою, у => є багато особливостей та прихованих функцій. Я рекомендую використовувати стрілочні функції тільки там, де вам потрібна нова функціональність:
- Функції з одиночними операторами, які відразу роблять повернення;
- функції, які повинні працювати з цим з батьківським scope.
ES6 має новий спосіб створення функцій - За допомогою оператора Стрілка => . Такі функції називаються стрілочними. Вони пропонують компактніший синтаксис. Вони не мають імені і вони по-своєму працюють з цим.
Перше, що ми зробимо, це запустимо скрипт Babel, який стежитиме за файлами та при їх зміні створювати свіжі версії.
Відкриємо папку проекту у командному рядку (КС). Вводимо команду:
І натиснути Enter
У папці src створимо файл arr.js і одразу вкажу його у файлі index.html
</script>
Останні версії браузерів підтримують стрілочні функції без транспіляції і мій браузер входить до їх числа.
Давайте напишемо функцію, яка складає два числа і повертає їхню суму. Назвемо функцію add.
Function add (x, y) ( return x + y; ) console.log (add (3, 6));
У консолі ми побачимо результат - 9
Тепер, давайте переведемо цю функцію стрілочну.
Приберемо слово function, приберемо ім'я функції та приберемо фігурні дужки, і слово – return. Після параметрів поставимо стрілку.
Let add = (x, y) => x + y; console.log (add (4, 6));
Якщо дивитися на тип змінної add використовуючи оператор typeof:
Console.log(typeof(add));
Що ми побачимо у консолі function
Це означає, що стрілочні функції це звичайні функції. І це можна переконатися подивившись на транспильований код.
"use strict"; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) ( return typeof obj; ) : function (obj) ( return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj ;); var add = function add(x, y) (return x + y;); console.log(add(4, 6)); console.log(typeof add === "undefined" ? "undefined" : _typeof(add));
Ми бачимо, що Babel перетворив наш код на простий вираз функцією.
Давайте напишемо просту функцію яка зводитиме задане число в квадрат.
Let add = (x, y) => x + y; console.log (add (4, 6)); console.log(typeof(add)); let square = function(a) ( return a * a; ) console.log(square (4));
Подивимося в консолі:
Стрілочна функція виглядатиме ось так:
Let square = x => x * x;
Якщо стрілочна функція приймає лише один параметр, немає необхідності укладати його в дужки!
Давайте напишемо функцію, яка взагалі не приймає параметрів.
Function givNumer() ( return 33; ) console.log(givNumer());
Ця функція просто виводить у консоль число 33.
Let givNumer = () => 33; console.log(givNumer());
Створимо функцію, яка не повертатиме нічого. Вона просто виведе повідомлення у консоль браузера.
Let log = function () ( console.log("Hello World!"); ); log();
Стрілочна:
Let log = () => console.log("Hello World!!!"); log();
Створимо функцію тіло якої складатиметься з двох рядків.
Функція прийматиме два параметри. Тілі функції створимо змінну. Після цього повернемо результат.
Let mult = function (a, b) ( let result = a * b; return result; ) console.log(mult (4, 5));
Якщо у стрілочній функції кілька рядків, то фігурні дужки – () обов'язкові! І обов'язково визначити те, що ця функція повертає, використовуючи ключове слово return
Стрілочна:
Let mult = (a, b) => ( let result = a * b; return result; ) console.log(mult (4, 5));
Тепер створимо функцію, яка повертає літерал об'єкта:
Let literal = function () ( return ( name: "John"); ) console.log (literal ());
У консолі ми побачимо:
Тепер спробуємо створити стрілочну функцію, яка повертатиме літерал об'єкта.
Слід пам'ятати, що якщо стрілочна функція повертає літерал об'єкта, то потрібні круглі дужки.
Стрілка функція, що повертає літерал об'єкта:
Let literal = () => ((name: "John")); console.log (literal());
Тепер спробуємо використовувати стрілочну функцію як IIFE - Immediately-invoked function expression
Якщо сказати коротко, то це функція, яка виконується одразу після оголошення
Це виглядає так:
(function () ( console.log("IIFE"); ))();
Стрілка IIFE - функція виглядатиме ось так:
(() => console.log("IIFE"))();
Важливою особливістю стрілочних функцій є те, що стрілка має йти одразу після параметрів!
Її не можна просто так взяти і спустити на рядок нижче. Видасть помилку!
Практичне застосування стрілочних функцій. Стрілецькі функції дуже зручно застосовувати з масивами.Давайте створимо масив з деякими числами та назвемо його numbers. Я думаю що ви знаєте, що масиви мають корисні методи, які дозволяють це масив перебирати, фільтрувати і т.д.
Давайте ви вважаємо суму всіх змінних масиву. Для цього я оголошу ще одну змінну – let sum = 0;
Скористаємося методом forEach() який є у кожного масиву, ми переберемо елементи та додамо до суми.
Let numbers =; let sum = 0; numbers.forEach(function(num) ( sum += num; )); console.log (sum);
У консолі ми побачимо 55 . Давайте перетворимо цю функцію на стрілочну: numbers.forEach(num => sum += num); console.log(sum);
Таким чином, те, що у нас раніше займало три рядки, тепер займає один.
Також ми можемо звести у квадрат кожен елемент масиву.
Let squared = numbers.map (n => n * n); console.log (squared);
Стрілецькі функції і це. Для цього я створимо літерал об'єкта, який збережу в змінну рerson.У об'єкта person буде властивість name зі значенням 'Bob' і властивості greet - привітати.
Let person = ( name: "Bob", greet: function () ( console.log("Hello! My name is " + this.name); console.log(this); ) ); person.greet();
У консолі браузера ми побачимо вітання і сам об'єкт person.
Тепер ми замінимо функцію на стрілочну і подивимося, що станеться з this .
Let person = ( name: "Bob", greet: () => ( console.log("Hello! My name is " + this.name); console.log(this); ) ); person.greet();
Тепер ми не отримали значення імені і як значення this-window!
Але чому? Справа в тому, що значення цього береться з контексту, в якому функція оголошена. ! Незалежно від того, де ця функція буде виконана. Це можна побачити на зображенні:
Ми маємо програму.
У ній поки що, крім об'єкта window, нічого немає. Додали об'єкт особи. Зауважте, що у методу ми використовуємо стрілочну функцію. Як ми й казали - значення цього буде братися з контексту. Контекст – це оточення. У разі оточенням об'єкта person , всіх його властивостей і методів, буде об'єкт window . І якщо значення this буде братися з контексту, this буде посилатися на об'єкт window .
Якщо ми розглянемо звичайну функцію, ми знаємо, що це посилається сам об'єкт person . Ви можете запитати, чому значення цього у стрілочних функціях береться з контексту? А відповідь дуже проста – їх так зробили! :-) Справа в тому, що стрілочні функції були створені для вирішення проблем в іншій ситуації. Давайте подивимося на прикладі. Для того, щоб побачити проблему, ми повернемося до нашої стрілочної функції.
Let person = ( name: "Bob", greet: function () ( console.log("Hello! My name is " + this.name); console.log(this); ) );
Уявимо, що наш Bob досить зайнятий і йому потрібно кілька секунд, щоб завершити свою роботу. Очікування в 2 сек. ми симулюємо з допомогою функції setTimeout(); . Як перший параметр ця функція приймає функцію і другим параметром - кількість мілісекунд, які необхідно почекати.
Let person = ( name: "Bob", greet: function () ( setTimeout(function () ( console.log("Hello! My name is " + this.name); console.log(this); ), 2000)) ;)); person.greet();
Якщо у вас є досвід роботи з JavaScript, то я думаю, що ви розумієте, в чому полягає проблема. Все одно, подивимося на те, що буде в браузері. Рівно через дві секунди ми побачимо в браузері таку картину.
Але чому? Якщо подивитися наш код, то логічно припустити. що це посилається на об'єкт person , тому що ми використовуємо звичайну функцію. Справа в тому, що setTimeout() належить об'єкту window. Якщо написати так: window.setTimeout() , то як ви думаєте, на що посилається thus ? І в консолі ми отримаємо той самий результат! ES5 має кілька способів вирішити цю проблему. Ми розглянемо найпоширеніший: Перед setTimeout() я оголошу ще одну змінну that і як значення надамо this . І тепер, у тілі функції замість this ми вкажемо that .
Let person = ( name: "Bob", greet: function () ( let that = this; setTimeout(function () ( console.log("Hello! My name is " + that.name); console.log(that) ;), 2000); person.greet();
Тепер завдяки замиканню Функція, яку ми відправляємо в setTimeout(), матиме доступ до змінної that , значенням якої буде this , тобто в даному випадку об'єкт person .
Можна наочності подивитися те що, що посилаються наші that і this .
Let person = ( name: "Bob", greet: function () ( let that = this; setTimeout(function () ( console.log("Hello! My name is " + that.name); console.log("It is my That = "+ that); console.log("It is my This = "+ this); ), 2000);))); person.greet();
У консолі ми побачимо підтвердження:
Ми бачимо, що this буде об'єктом вікна - This = , а that буде об'єктом нашого person - That = .
В ES6 для вирішення цієї проблеми ми можемо просто використовувати стрілочну функцію.
Let person = ( name: "Bob", greet: function () ( setTimeout(() => ( console.log("Hello! My name is " + this.name); console.log("It is my This = "+ this); ), 2000); ))); person.greet();
У результаті ми в консолі побачимо:
У графічному прикладі для стрілочної функції контекстом буде об'єкт person, а не об'єкт window. саме тому this буде посилатися на person.
Крім компактного синтаксису, стрілочні функції були введені для вирішення таких проблем.
Як ознайомлення, ви можете подивитися як вирішив це Babel
Var person = ( name: "Bob", greet: function greet() ( var _this = this; setTimeout(function () ( console.log("Hello! My name is " + _this.name); console.log(" It is my This = "+ _this); ), 2000);))); person.greet(); Babel використовував той же метод, що і ми в ES5. Вся різниця в тому, що ми називали змінну that , а Babel назвав - _this . Завдяки замиканню, функція яку ми відправляємо в setTimeout, матиме доступ до змінної _this і як наслідок - до об'єкта person.
Думаю, що найважче в цій частині – це зрозуміти як працюють замикання.
Ще деякі особливості стрілочних функцій:
Ще інформацію щодо ES6 та стрілочних функцій ви можете переглянути в моєму пості
- Tutorial
Однією з найцікавіших частин нового стандарту ECMAScript 6 є стрілочні функції. Стрілецькі функції, як і зрозуміло з назви, визначаються новим синтаксисом, який використовує стрілку => . Однак, крім відмінного синтаксису, стрілочні функції відрізняються від традиційних функцій та інших моментах:
- Лексичне зв'язування. Значення спеціальних змінних this , super і arguments визначаються тим, як стрілочні функції були викликані, а тим, як вони були створені.
- Незмінні this, super і arguments. Значення цих змінних усередині стрілочних функцій залишаються незмінними протягом усього життєвого циклу функції.
- Стрілецькі функції не можуть бути використані як конструктор і кидають помилку при використанні з оператором new.
- Недоступність власного значення змінної arguments .
Примітка: Ця стаття - це компіляція з вільного перекладу статті Understanding ECMAScript 6 arrow functions та читання останньої чернетки специфікації (January 20, 2014 Draft Rev 22).
Var fun = (x) => x;
Він дуже схожий на аналогічний синтаксис у таких мовах як Scala, CoffeeScript та синтаксис lambda-виразів з C#.
Синтаксис стрілочних функцій може бути різним, залежно від того, як ви оголошуєте функцію. Оголошення завжди починається зі списку аргументів, далі слідує стрілка та тіло функції. І список аргументів, і тіло функції можуть мати різну форму залежно від того, що ви пишете.
Один параметр Оголошення стрілочної функції, яка приймає один аргумент і просто повертає його, виглядає дуже просто:Var reflect = value => value; // еквівалент var reflect = function(value) ( return value; )
Коли стрілочна функція має лише один аргумент, то він може бути оголошений без дужок. Наступне після стрілки тіло функції може бути без фігурних дужок і може не містити ключового слова return .
Var sum = (num1, num2) => num1 + num2; // еквівалент var sum = function(num1, num2) (return num1 + num2;);
Функція sum просто підсумовує два аргументи. Єдина відмінність від попереднього прикладу в наявності круглих дужок та коми (прямо як у традиційних функціях).
Var sum = () => 1 + 2; // еквівалент var sum = function() ( return 1 + 2; );
Традиційний синтаксис тіла функції Ви можете скористатися синтаксисом традиційних функцій для тіла стрілочної функції, коли воно містить більше одного виразу. Тобто обернути функцію у фігурні дужки та додати ключове слово return :Var sum = (num1, num2) => (return num1 + num2;) // еквівалент var sum = function(num1, num2) (return num1 + num2;);
Тіло функції буде оброблено точно так, як і у випадку класичних функцій, за винятком того, що значення спеціальних змінних this , super та arguments будуть обчислюватися по-іншому.
Var getTempItem = id => ((id: id, name: "Temp")); // еквівалент var getTempItem = function(id) (return (id: id, name: "Temp"));
Поміщення літералу об'єкта в круглі дужки показує парсеру, що фігурні дужки це початок традиційного синтаксису для тіла функції, а початок літерала.
Var getTempItems = (...rest) => rest; // еквівалент var getTempItems = function() ( return .slice.apply(arguments) );
Шаблон деструктуризації як параметр У рамках цієї статті ми не розглядаємо шаблони деструктуризації - ви можете прочитати про них у статті Огляд ECMAScript 6, наступної версії JavaScript, хоча ця інформація частково застаріла.Як видно з попереднього прикладу, незважаючи на те, що у стрілочної функції лише один аргумент, все одно необхідно застосовувати круглі дужки при використанні шаблонів деструктуризаціїяк єдиний параметр функції. Приклади з іншими шаблонами:
Var a = ((a)) => a; var b = ([b]) => b;
Використання стрілочних функцій Встановлення контексту Одним із частих сценаріїв JavaScript є встановлення правильного значення цього всередині функції (зв'язування). Оскільки значення цього може бути змінено, то, залежно від контексту виконання функції, можливо помилково впливати на один об'єкт, коли ви мали на увазі зовсім інший. Подивіться наступний приклад:Var pageHandler = ( id: "123456" , init: function() ( document.addEventListener("click", function(event) ( this.doSomething(event.type); // помилка )); ) , doSomething: function( type) ( console.log ( " Handling " + type + " for " + this.id) ) );
У наведеному коді об'єкт pageHandler повинен обробляти кліки на сторінці. Метод init() навішує обробник на потрібну подію, який у собі викликає this.doSomething() . Проте код відпрацює неправильно. Посилання на this.doSomething() не є валідним, оскільки це вказує на об'єкт document всередині обробника події замість планованого pageHandler . При спробі виконати цей код ви отримаєте помилку, оскільки об'єкт document не має методу doSomething .
Ви можете зав'язати це значення на об'єкті pageHandler, використовуючи handleEvent або викликавши у функції стандартний метод bind() :
Var pageHandler = ( id: "123456" , init: function() ( document.addEventListener("click", (function(event) ( this.doSomething(event.type); // error )).bind(this))) ; ) , doSomething: function(type) ( console.log("Handling " + type + " for " + this.id) ) );
Тепер код працює так, як і думалося, але виглядає більш громіздко. Крім того, викликаючи bind(this) ви щоразу створюєте нову функцію, значення this якої зав'язане на значенні pageHandler , але код працює так, як ви задумували.
Стрілецькі функції вирішують проблему більш елегантним способом, оскільки використовують лексичне зв'язування значення this (а також super і arguments ) і його значення визначається значенням this у тому місці, де стрілочна функція була створена. Наприклад:
Var pageHandler = ( id: "123456" , init: function() ( document.addEventListener("click", event => this.doSomething(event.type)); ) , doSomething: function(type) ( console.log( "Handling" + type + "for" + this.id))));
У цьому прикладі обробник це стрілочна функція, в якій викликається this.doSomething() . Значення this буде тим самим, що і функції init() , і код в даному прикладі відпрацює правильно, аналогічно тому, який використовував bind() . Незалежно від того, чи повертає виклик this.doSomething() значення чи ні, вираз усередині тіла стрілочної функції не потрібно обрамляти у фігурні дужки.
Крім того, приклад вищий ще й ефективніший за виклик bind() , тому що для браузера він аналогічний наступному коду:
Var pageHandler = ( id: "123456" , init: function() ( var self = this; document.addEventListener( "click", function(event) ( return self.doSomething(event.type) )); ) , doSomething: function(type) ( console.log("Handling" + type + "for" + this.id) ) );
Тобто не відбувається створення нової функції, як у разі виклику bind() .
Var obj = ( arr1: , arr2: ["a", "b", "c"] , concatenate: function(a, b)( return a + "|" + b ) , intersection: function() ( return this .arr1.reduce((sum, v1) => // arrow function 1 this.arr2.reduce((sum, v2) => ( // arrow function 2 sum.push(this.concatenate(v1, v2)) return sum;)), sum),)))); var arrSum = obj.intersection();//["1|a", "1|b", "1|c", "2|a", "2|b", "2|c", "3 |a", "3|b", "3|c"]
Використання як аргумент Короткий синтаксис стрілочних функцій робить їх ідеальними кандидатами на передачу як аргументи на виклик інших функцій. Наприклад, якщо ви хочете відсортувати масив, то зазвичай пишете щось на кшталт такого:Var result = values.sort(function(a, b) ( return a - b ));
Досить багатослівно для простої операції. Порівняйте з коротким записом стрілочної функції:
Var result = values.sort((a, b) => a - b);
Використання таких методів, як масивні sort() , map() , reduce() тощо, може бути спрощено з використанням короткого синтаксису стрілочної функції.
- Оператор типуповерне "функцію" для стрілочної функції
- Стрілочна функція також екземпляр «класу» Function, тому instanceof спрацює так само, як і з традиційною функцією
- Ви все ще можете використовувати методи call() , apply() і bind() , однак пам'ятайте, що вони не будуть впливати на значення this
- Ви можете використовувати метод toMethod() , однак він не змінюватиме значення super ( метод toMethod() введений в es6 і не розглядається в рамках цієї статті).
Короткий синтаксис дозволить писати складні речі ще складніше простіше. Наприклад, так буде виглядати генератор ідентифікаторів (який на es5 виглядає куди багатослівнішим):
Let idGen = (start = 0, id = start, reset = (newId = start) => id = newId, next = () => id++) => ((reset, next)); let gen = idGen(100); console.log(gen.next(), gen.next(), gen.reset(10), gen.next());//100 101 10 10
А лексичне зв'язування закриє одне з найбільших джерел болю та розчарування для розробників, а також покращить продуктивність за рахунок оптимізації на рівні js-движка.
Якщо ви хочете спробувати стрілочні функції, то можете виконати вищезгадані приклади в консолі Firefox, який на даний момент (02.2014 FF28) майже повноцінно підтримує стрілочні функції (FF28 неправильно обчислює значення arguments).
Також ви можете спробувати стрілочні функції та інші можливості es6 в онлайн трансляторі Traceur.
Теги: Додати теги
Всім привіт! У цій статті ми розглянемо, що таке стрілочні функції ES6 і як їх використовувати .
Функції стрілки – це функції, які записуються за допомогою оператора "стрілка" (=>).
Давайте відразу розглянемо приклад:
Let add = (x, y) => x + y;
console.log(add(5, 2));
В результаті виконання цієї функції в консолі побачимо число 7.
Спочатку, у круглих дужках ми передаємо аргументи, далі ставимо знак стрілочки, а потім пишемо код самої функції. У нашому випадку вона просто приймає два числа та складає їх. За ідеєю, це те саме, що й функція Expression в ES5 . Якщо ви використовуєте Babel або подібні компілятори, то, швидше за все, вони напишуть щось на зразок цього:
Var add = функція add(x, y) (
return x + y;
};
Якщо функція приймає лише один параметр, круглі дужки ставити необов'язково.
Let square = x => x * x;
Така функція приймає лише один аргумент і зводить передане число квадрат.
Функція без параметрів:
Let func = () => 77;
Якщо ваша функція містить кілька рядків, то, по-перше, потрібно використовувати фігурні дужки, а по-друге, обов'язково написати, що функція повертає, тобто. використовувати ключове слово return.
Let multiply = (x, y) => (
let result = x * y;
return result;
};
Якщо вам потрібно повернути літерал об'єкта, його потрібно обернути в круглі дужки:
Let getObject = () => ((brand: "BMW"));
Функція, що самовикликається, виглядає наступним чином.
Угору функція expression є syntactically compact alternative до regular function expression , але без його своїх bindings до цього , arguments , super , або New.target keywords. Рівень функцій expressions є ill suited as methods, and they cannot be used as constructors.
Syntax Basic syntax (param1, param2, …, paramN) => ( statements ) (param1, param2, …, paramN) => expression // equivalent to: => ( return expression; ) // Parentheses are optional when there"s тільки один parameter name: (singleParam) => ( statements ) singleParam => ( statements ) // The parameter list for function with no parameters should be written with pair of parentheses () => ( statements ) Advanced syntax // Взаємодія з функцією до відновленого об'єкта літературного дзвінка: params => ((foo: bar)) // Інші параметри і деякі параметри є supported (param1, param2, ...rest) => ( statements ) (param1 = defaultValue1, param2, …, paramN = defaultValueN) => ( statements ) // Destructuring within the parameter list is also supported var f = ( = , (x: c) = (x: a + b)) => a + b + c; f(); // 6 DescriptionДва фактори influenced до введення arrow функцій: потрібні для shorter функцій і behavior of the keyword.
Shorter functions var elements = ["Hydrogen", "Helium", "Lithium", "Beryllium"]; / / Цей стан returns the array: elements.map (function (element) ( return element.length; )); // Регулярна функція може бути написана як arrow функція нижче elements.map((element) => ( return element.length; )); // // Якщо є лише один parameter, ми можемо remove the surrounding parentheses elements.map (element => ( return element.length; )); // // Коли тільки станція в arrow функції є `return`, ми можемо remove `return` and remove // surrounding curly brackets elements.map(element => element.length); // // У цьому випадку, тому що тільки потрібно, щоб length properties, ми можемо використовувати деструктивний parameter: // Notice that the `length` corresponds to the property we want to get whereas the // obviously non-special `lengthFooBArX` is Just the name of variable which can be changed // to any valid variable name you want elements.map ((( length:lengthFooBArX )) => lengthFooBArX); // // Цей параметр деструкції вимірювання може бути написаний як білий. However, note that in // Цей example we не є assigning `length` value to the made up property. Instead, literal name // itself of the variable `length` is used as the property we want to retrieve from the object. elements.map (((length)) => length); // No separate thisПісля функцій, новим новим функцією було визначено, що його ця величина базується на тому, що функція була названа:
- Новий об'єкт у випадку конструктора.
- undefined in strict mode function calls.
- Основний об'єкт, якщо функція була названа як "object method".
Це зроблено для того, щоб бути бездоганним з object-oriented style of programming.
Function Person() ( // The Person() constructor defines `this` as instance of itself. this.age = 0; setInterval(function growUp() ( // In non-strict mode, the growUp() function defines ` this` // як global object (because it"s where growUp() is executed.), // which is different from the `this` // defined by the Person() constructor. this.age++; ), 1000) ;) var p = new Person();
У ECMAScript 3/5, ця сума була спрямована на визначення значення в цьому параметрі, що може бути заблоковано.
Function Person() ( var that = this; that.age = 0; setInterval(function growUp() ( // The callback refers to the `that` variable of which // the value is the expected object. that.age++; )) , 1000);) "use strict"; var obj = (a: 10); Object.defineProperty(obj, "b", ( get: () => ( console.log(this.a, typeof this.a, this)); // undefined "undefined" Window (...) (or the global object) return this.a + 10; // represents global object "Window", therefore "this.a" returns "undefined")));
Use of the new operatorArrow functions cannot be used as constructors and will throw an error when used with new .
Var Foo = () => (); var foo = New Foo (); //TypeError: Foo is not a constructor
Use of prototype propertyНалаштування функцій не має prototype property.
Var Foo = () => (); console.log(Foo.prototype); // undefined
Use of the yield keywordВони не можуть бути використані в arrow functions's body (за винятком коли можливі з функціями, які не існують без нього).
Function bodyНабір функцій може мати її "концентрація тіла" або звичайний "блоковий пристрій".
In a concise body, тільки expression is specified, which becomes the implicit return value. У блоці, ви повинні використовувати explicit return statement.
Var func = x => x * x; // concise body syntax, іmplied "return" var func = (x, y) => (return x + y;); // with block body, explicit "return" needed
Returning object literalsKeep в думці, що відновити об'єкт літералів, використовуючи концепцію тіла syntax params => (object:literal) не буде працювати як expected.
Var func = () => (foo: 1); // Calling func() returns undefined! var func = () => (foo: function() ()); // SyntaxError: Function statement requires a name
Це означає, що код всередині браузів (()) є послідовним як записи статей (і.е. foo is treated like a label, no key in an object literal).
Ви повинні загорнути object literal in parentheses:
Var func = () => ((foo: 1));
Line breaksУ ході функцій може бути не визначено line break між його параметрами і його арrow.
Var func = (a, b, c) => 1; // SyntaxError: expected expression, got "=>"
Хоча, це може бути спрямований на те, щоб підняти лінію перерви після шипування або використання parentheses/braces, щоб бути вільним, щоб забезпечити, що code stays pretty and fluffy. Ви можете також брати line breaks між argumentами.
Var func = (a, b, c) => 1; var func = (a, b, c) => (1); var func = (a, b, c) => (return 1); var func = (a, b, c) => 1; // no SyntaxError thrown
Parsing orderБільше, як arrow in arrow function не є оператором, arrow функцій має особливі віртуальні правила, що interact differently with operator precedence compared to regular functions.
Let callback; callback = callback | function() (); // ok callback = callback | () => (); // SyntaxError: invalid arrow-function arguments callback = callback || (() => ()); // ok
More examples // An empty arrow function returns undefined let empty = () => (); (() => "foobar")(); // Returns "foobar" // (Це є безпосереднім Invoked Function Expression) var simple = a => a > 15 ? 15: a; simple(16); // 15 simple(10); // 10 let max = (a, b) => a > b? a: b; // Easy array filtering, mapping, ... var arr =; var sum = arr.reduce((a, b) => a + b); // 66 var even = arr.filter(v => v % 2 == 0); // var double = arr.map (v => v * 2); // // More concise promise chains promise.then(a => ( // ... )).then(b => ( // ... )); // Parameterless arrow functions that are visually easier to parse setTimeout(() => ( console.log("I happen sooner"); setTimeout(() => ( // deeper code console.log("I happen later") ; ), 1); SpecificationsECMAScript 2015 (6th Edition, ECMA-262) |
Standard | Initial definition. |
ECMAScript Latest Draft (ECMA-262) Definition of "Arrow Function Definitions" в цій specification. |
Draft |
Компактність таблиці на цій сторінці генерується з структурованих даних. Якщо ви знайдете, щоб дізнатися про ваші дані, клацніть на https://github.com/mdn/browser-compat-data і пишуть.
Update compatibility data on GitHub
Desktop Mobile Server | ||||||||||||
Chrome Full support 45 | Edge Full support Yes | Firefox Full support 22 Notes Full support 22Notes Notes Prior to Firefox 39, line terminator (\n) був incorrectly allowed after arrow function arguments. Це має бути fixed до conform to ES2015 specification and code like () \n => | IE No support No | Opera Full support 32 | Safari Full support 10 | WebView Android Full support 45 | Chrome Android Full support 45 | Firefox Android Full support 22 Notes Full support 22Notes Notes Ініційна реалізація arrow функцій в Firefox створена для них автоматично strict. Це буде змінено як Firefox 24. За допомогою "використання"; is now required. Notes Prior to Firefox 39, line terminator (\n) був incorrectly allowed after arrow function arguments. Це буде fixed до conform to ES2015 specification and code like () \n => () will now throw a SyntaxError в цій і останньої версії. | Opera Android Full support 32 | Safari iOS Full support 10 | Samsung Internet Android Full support 5.0 | nodejs Full support Yes |
Chrome Full support 58 | Edge? | Firefox Full support 52 | IE No support No | Opera Full support 45 | Safari? | WebView Android Full support 58 | Chrome Android Full support 58 | Firefox Android Full support 52 | Opera Android Full support 43 | Safari iOS? | Samsung Internet Android Full support 7.0 | nodejs Full support Yes |