0

В чем разница (если она есть) между стрелочными функциями ES6 и функциями, связанными с помощью Function.prototype.bind?

13

Похоже, что в ES6 следующие две функции очень похожи:

function () {
  return this;
}.bind(this);

() => {
  return this;
};

Результат выполнения этих функций кажется одинаковым: стрелочные функции создают объект функции JavaScript с контекстом this, привязанным к тому же значению, к которому привязан this во время их создания.

Очевидно, что в общем смысле Function.prototype.bind более гибок, чем стрелочные функции: он может привязывать к значениям, отличным от локального this, и может привязывать this любой функции в любой момент времени, потенциально значительно позже, чем она изначально создана. Однако я не спрашиваю, чем bind отличается от стрелочных функций, я спрашиваю, чем стрелочные функции отличаются от немедленного вызова bind с this.

Есть ли какие-либо различия между этими двумя конструкциями в ES6?

2 ответ(ов)

0

Существует несколько отличий:

  1. Строковые функции не могут быть конструированы. Хотя как стрелочные функции, так и связанные функции не имеют свойства .prototype, первые выбрасывают исключение при вызове с new, тогда как вторые просто игнорируют связанное значение и вызывают целевую функцию как конструктор (хотя и с частично применёнными связанными аргументами) для нового экземпляра.

    function F() {}
    var f = () => {},
        boundF = F.bind({});
    console.log(new boundF(), new boundF instanceof F) // {}, true
    console.log(new f) // TypeError
    
  2. Стрелочные функции имеют лексические arguments, new.target и super. Вызов стрелочной функции не инициализирует ни одно из этих значений, они просто наследуются от функции, в которой была определена стрелочная функция. В связанном функции они просто ссылаются на соответствующие значения целевой функции.

  3. Стрелочные функции на самом деле не связывают значение 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;
    
  4. Стрелочные функции не могут быть генераторными функциями. Хотя они могут возвращать генераторы, вы не можете использовать .bind() для генераторной функции, и нет способа выразить это с помощью стрелочной функции.

0

Вот еще одно тонкое различие:

Стрелочные функции могут возвращать значение без использования ключевого слова '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, чтобы явно указать, что возвращаемый результат — это объект.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь