Каковы различия (если таковые имеются) между функциями стрелок ES6 и функциями, связанными с Function.prototype.bind?
Мне кажется, что в ES6 следующие две функции почти идентичны:
function () {
return this;
}.bind(this);
() => {
return this;
};
Конечный результат выглядит одинаково: функции со стрелками создают объект функции JavaScript со своими this
контекст привязан к тому же значению, что и this
где они созданы.
Очевидно, в общем смысле Function.prototype.bind
более гибок, чем функции стрелок: он может связываться со значениями, отличными от локальных this
и может связать любую функцию this
в любой момент времени, потенциально еще долго после его создания. Тем не менее, я не спрашиваю, как bind
само по себе отличается от функций со стрелками, я спрашиваю, как функции со стрелками отличаются от непосредственного вызова bind
с this
,
Есть ли различия между двумя конструкциями в ES6?
3 ответа
Нет (значительных) различий.
Ну, хорошо, это немного преждевременно. Есть три крошечных различия, уникальных для функций стрелок.
Функции стрелок нельзя использовать с
new
,Это означает, конечно, что они не имеют
prototype
свойство и не может использоваться для создания объекта с классическим синтаксисом.new (() => {}) // TypeError: () => {} is not a constructor
Это, вероятно, к лучшему, хотя
new
Работы не будут иметь большого смысла со связанными функциями.Функции стрелок не имеют доступа к специальным
arguments
объект, к которому имеют доступ обычные функции JavaScript.(() => arguments)(1, 2, 3) // ReferenceError: arguments is not defined
Этот, вероятно, немного больше гоча. Предположительно это сделано для того, чтобы убрать одну из других странностей JavaScript.
arguments
объект - это свое особое чудовище, и у него странное поведение, поэтому неудивительно, что его выбросили.Вместо этого в ES6 есть знаки, которые могут выполнить то же самое без каких-либо волшебных скрытых переменных:
((...args) => args)(1, 2, 3) // [1, 2, 3]
Функции стрелок не имеют своих
new.target
собственность, они используютnew.target
их вмещающей функции, если она существует.Это согласуется с другими изменениями для удаления "магически" введенных значений для функций стрелок. Это конкретное изменение особенно очевидно, учитывая, что функции стрелок нельзя использовать с
new
во всяком случае, как упоминалось выше.
В противном случае стрелки семантически подобны связанным функциям. Стрелки могут быть более производительными, так как им не нужно носить с собой дополнительный багаж и их не нужно сначала преобразовывать из обычных функций, но по поведению они точно такие же.
Есть несколько отличий:
Функции стрелок не могут быть построены. В то время как функции со стрелками и связанные функции не имеют
.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, // works boundF = function(){ return this; }.bind(this); // ^^^^ ReferenceError super(); // initialises `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}