Сводка
Выражения стрелочных функций имеют более короткий синтаксис по сравнению с функциональными выражениями и лексически привязаны к значению this (но не привязаны к собственному this, arguments, super, или new.target). Стрелочные функции всегда анонимные.
Синтаксис
// Basic syntax: (param1, param2, paramN) => { statements } (param1, param2, paramN) => expression // equivalent to: => { return expression; } // Parentheses are optional when there's only one argument: (singleParam) => { statements } singleParam => { statements } // A function with no arguments requires parentheses: () => { statements } // Advanced: // Parenthesize the body to return an object literal expression: params => ({foo: bar}) // Rest parameters are supported (param1, param2, ...rest) => { statements }
Подробные примеры синтаксиса можно посмотреть здесь.
Описание
Два фактора повлияли на появление стрелочных функции: более короткий синтаксис и лексика this.
Короткие функции
В некоторых функциональных шаблонах приветствуются более короткие функции. Сравните:
var a = [ "Hydrogen", "Helium", "Lithium", "Beryllium" ]; var a2 = a.map(function(s){ return s.length }); var a3 = a.map( s => s.length );
Лексика this
До появления стрелочных функций, каждая новая функция имела своё значение this (новый объект в случае конструктора, undefined в строгом режиме вызова функции, контекст объекта при вызове функции как "метода объекта" и т.д.). Это очень раздражало при использовании объектно-ориентированного стиля программирования.
function Person() {
// В конструктор Person() `this`
указывает на себя.
this.age = 0;
setInterval(function growUp() {
// В нестрогом режиме, в функции growUp() `this` указывает
// на глобальный объект, который отличается от `this`,
// определяемом в конструкторе Person().
this.age++;
}, 1000);
}
var p = new Person();
В ECMAScript 3/5, данная проблема решалась присваиванием значения this
близко расположенной переменной:
function Person() { var self = this; // Некоторые выбирают `that` вместо `self`. // Выберите один вариант и следуйте ему. self.age = 0; setInterval(function growUp() { // В функции используется переменная `self`, которая // имеет значение требуемого объекта. self.age++; }, 1000); }
Также, может быть создана привязанная функция, в которой задаётся требуемое значение this
для функции growUp
.
Стрелочные функции захватывают значение this
окружающего контекста, поэтому нижеприведенный код работает как предполагалось:
function Person(){ this.age = 0; setInterval(() => { this.age++; // `this` указывает на объект Person }, 1000); } var p = new Person();
Строгий режим исполнения
Поскольку значение this
определяется лексикой, правила строгого режима относительно this
игнорируются:
var f = () => {'use strict'; return this}; f() === window; // или глобальный объект
Оставшиеся правила строго режима применяются как обычно.
Вызов с помощью call или apply
Так как значение this определяется лексикой, вызов стрелочных функций с помощью методов call() или apply(), даже если передать аргументы в эти методы, не влияет на значение this:
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
Объект arguments
Стрелочные функции не имеют собственного объекта arguments, поэтому в теле стрелочных функций arguments будет ссылаться на переменную в окружающей области.
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
В большинстве случаев лучшей заменой объекта arguments в стрелочных функциях являются rest параметры:
function foo() {
var f = (...args) => args[0];
return f(2);
}
foo(1); // 2
Использование ключевого слова yield
Ключевое слово yield не может быть использовано в теле стрелочной функции (за исключением случаев, когда разрешается использовать в функциях, вложенных в тело стрелочной функции). Как следствие стрелочные функции не могут быть использованы как генераторы.
Тело функции
Тело стрелочной функции может иметь краткую (concise body) или блочную (block body) форму.
Блочная форма не возвращает значение, необходимо явно вернуть значение.
var func = x => x * x; // краткий синтаксис,
// неявно возвращает результат
var func = (x, y) => { return x + y; }; // блочный синтаксис,
// явно возвращает результат
Примеры
// Пустая стрелочная функция возвращает undefined let empty = () => {}; (() => "foobar")() // вернёт "foobar" var simple = a => a > 15 ? 15 : a; simple(16); // 15 simple(10); // 10 var complex = (a, b) => { if (a > b) { return a; } else { return b; } }
Спецификации
Спецификация | Статус | Комментарий |
---|---|---|
ECMAScript 2015 (6th Edition, ECMA-262) Определение 'Arrow Function Definitions' в этой спецификации. |
Стандарт | Изначальное определение. |
Совместимость с браузерами
Возможность | Chrome | Firefox (Gecko) | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|
Базовая поддержка | 45.0 | 22.0 (22.0) | Нет | Нет | Нет |
Возможность | Android | Chrome for Android | Firefox Mobile (Gecko) | IE Mobile | Opera Mobile | Safari Mobile |
---|---|---|---|---|---|---|
Базовая поддержка | Нет | 45.0 | 22.0 (22.0) | Нет | Нет | Нет |
Замечания для Firefox
- Первоначальная реализация стрелочных функций в Firefox автоматически переводила их в строгий режим. Это поведение было изменено в Firefox 24. Использование
"use strict";
стало обязательным. - Стрелочные функции семантически отличаются от нестандартных Expression Closures, добавленных в Firefox 3 (подробности в Javascript 1.8); в Expression Closures значение
this
не привязано лексически.