В чем разница (если она есть) между стрелочными функциями ES6 и функциями, связанными с помощью Function.prototype.bind?
Похоже, что в ES6 следующие две функции очень похожи:
function () {
return this;
}.bind(this);
() => {
return this;
};
Результат выполнения этих функций кажется одинаковым: стрелочные функции создают объект функции JavaScript с контекстом this
, привязанным к тому же значению, к которому привязан this
во время их создания.
Очевидно, что в общем смысле Function.prototype.bind
более гибок, чем стрелочные функции: он может привязывать к значениям, отличным от локального this
, и может привязывать this
любой функции в любой момент времени, потенциально значительно позже, чем она изначально создана. Однако я не спрашиваю, чем bind
отличается от стрелочных функций, я спрашиваю, чем стрелочные функции отличаются от немедленного вызова bind
с this
.
Есть ли какие-либо различия между этими двумя конструкциями в ES6?
2 ответ(ов)
Существует несколько отличий:
Строковые функции не могут быть конструированы. Хотя как стрелочные функции, так и связанные функции не имеют свойства
.prototype
, первые выбрасывают исключение при вызове сnew
, тогда как вторые просто игнорируют связанное значение и вызывают целевую функцию как конструктор (хотя и с частично применёнными связанными аргументами) для нового экземпляра.function F() {} var f = () => {}, boundF = F.bind({}); console.log(new boundF(), new boundF instanceof F) // {}, true console.log(new f) // TypeError
Стрелочные функции имеют лексические
arguments
,new.target
иsuper
. Вызов стрелочной функции не инициализирует ни одно из этих значений, они просто наследуются от функции, в которой была определена стрелочная функция. В связанном функции они просто ссылаются на соответствующие значения целевой функции.Стрелочные функции на самом деле не связывают значение
this
. У них нет своегоthis
, и когда вы используетеthis
, оно ищется как имя переменной в лексической области видимости. Это позволяет вам лениво определять стрелочную функцию, покаthis
ещё недоступен:class X extends Object { constructor() { var f = () => this, // всё работает boundF = function() { return this; }.bind(this); // ^^^^ ReferenceError super(); // инициализирует `this` console.log(f(), f() == this); // {}, true } } new X;
Стрелочные функции не могут быть генераторными функциями. Хотя они могут возвращать генераторы, вы не можете использовать
.bind()
для генераторной функции, и нет способа выразить это с помощью стрелочной функции.
Вот еще одно тонкое различие:
Стрелочные функции могут возвращать значение без использования ключевого слова 'return', если убрать фигурные скобки сразу после ⇒.
var f = x => x; console.log(f(3)); // 3
var g = x => { x }; console.log(g(3)); // undefined
var h = function(x) { x }; console.log(h(3)); // undefined
var i = x => { a: 1 }; console.log(i(3)); // undefined
var j = x => ({ a: 1 }); console.log(j(3)); // {a: 1}
В данном примере стрелочная функция f
возвращает значение x
напрямую, так как фигурные скобки не используются, и это позволяет избежать явного указания return
. В то время как в функции g
и обычной функции h
фигурные скобки приводят к тому, что возвращаемое значение составляет undefined
.
Важно также отметить, что в функции i
фигурные скобки есть, но выражение a: 1
не является корректным способом возвращения объекта — вместо этого нужно использовать скобки, как в функции j
, чтобы явно указать, что возвращаемый результат — это объект.
ECMAScript 6: Стрелочная функция, возвращающая объект
Соответствуют ли 'Стрелочные функции' и 'Функции' или они взаимозаменяемы?
Официальная информация о `arguments` в стрелочных функциях ES6?
Синтаксис асинхронной стрелочной функции
Можно ли задать имя файла объекта PDF, отображаемого в Chrome?