Стрелочные функции (Arrow functions) в ECMAScript 6

  • Tutorial
Arrow functions madness
Одной из самых интересных частей нового стандарта ECMAScript 6 являются стрелочные функции. Стрелочные функции, как и понятно из названия определяются новым синтаксисом, который использует стрелку =>. Однако, помимо отличного синтаксиса, стрелочные функции отличаются от традиционных функций и в других моментах:
  • Лексическое связывание. Значения специальных переменных this, super и arguments определяются не тем, как стрелочные функции были вызваны, а тем, как они были созданы.
  • Неизменяемые this, super и arguments. Значения этих переменных внутри стрелочных функций остаются неизменными на протяжении всего жизненного цикла функции.
  • Стрелочные функции не могут быть использованы как конструктор и кидают ошибку при использовании с оператором new.
  • Недоступность «собственного» значения переменной arguments.

Было несколько причин для введения этих отличий. Первоочередная — это то, что связывание (binding) используется довольно часто в JavaScript. Очень легко потерять нужное значение this при использовании традиционных функций, что может привести к непредсказуемым последствиям. Другая причина, это то, что JS-движки смогут легко оптимизировать выполнение стрелочных функций за счет этих ограничений (в противоположность традиционным функциям, которые могут быть использованы в качестве конструктора и которые свободны для модификации специальных переменных).


Примечание: Данная статья — это компиляция из вольного перевода статьи 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" } };

Помещение литерала объекта в круглые скобки указывает парсеру, что фигурные скобки это не начало традиционного синтаксиса для тела функции, а начало литерала.

Переменное число параметров


Так как «собственный» объект arguments не доступен внутри стрелочной функции (значение arguments лексически связано со значением arguments традиционной функции, внутри которой стрелочная функция была объявлена), то для стрелочных функций с переменным числом параметров нужно использовать rest-паттерн из шаблонов деструктуризации. Пример:

var getTempItems = (...rest) => rest;
// эквивалент
var getTempItems = function() { return [].slice.apply(arguments) };

Шаблон деструктуризации в качестве параметра


В рамках данной статьи мы не рассматриваем шаблоны деструктуризации — вы можете почитать про них в статье Обзор ECMAScript 6, следующей версии JavaScript, хотя эта информация частично устарела.

Как видно из предыдущего примера, несмотря на то, что у стрелочной функции всего один аргумент, всё равно необходимо применять круглые скобки при использовании шаблонов деструктуризации как единственного параметра функции. Примеры с другими шаблонами:

var a = ({a}) => a;
var b = ([b]) => b;


Использование стрелочных функций



Установка контекста


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

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() не валидна, поскольку this указывает на объект document внутри обработчика события вместо планируемого pageHandler. При попытке выполнить этот код, вы получите ошибку, поскольку объект document не имеет метода doSomething.

Вы можете завязать значение this на объекте 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().

«Прокидывание» контекста между несколькими вызовами


Очевидно, что можно вкладывать одну стрелочную функцию в другую, тем самым «прокидывая» значение this через них:

var obj = {
    arr1: [1, 2, 3]
    , 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() и так далее, может быть упрощено с использованием короткого синтаксиса стрелочной функции.

Другие особенности стрелочных функций



Несмотря на то, что стрелочные функции отличаются от традиционных функций, у них есть общие черты:
  • Оператор typeof вернёт "function" для стрелочной функции
  • Стрелочная функция также экземпляр «класса» Function, поэтому instanceof сработает так же как, и с традиционной функцией
  • Вы всё ещё можете использовать методы call(), apply(), и bind(), однако помните, что они не будут влиять на значение this
  • Вы можете использовать метод toMethod(), однако он не будет менять значение super (метод toMethod() введён в es6 и не рассматривается в рамках данной статьи).

Существенным отличием от традиционных функций является то, что попытка вызвать стрелочную функцию с указанием оператора new вызовет ошибку исполнения.

Итог



Стрелочные функции это одно из интереснейших нововведений в ECMAScript 6, которое, имея краткий синтаксис определения, упростит передачу функций в качестве значения параметра другой функции.

Лаконичный синтаксис позволит писать сложные вещи ещё сложнеепроще. Например, так будет выглядеть генератор идентификаторов (который на 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-движка.
Madness in FF
Если вы хотите попробовать стрелочные функции, то можете выполнить вышеуказанные примеры в консоли Firefox, который на данный момент (02.2014 FF28) почти полноценно поддерживает стрелочные функции (FF28 неправильно вычисляет значение arguments).

Также вы можете попробовать стрелочные функции и другие возможности es6 в онлайн трансляторе Traceur.
Mail.ru Group
1,156.33
Building the Internet
Share post

Comments 62

    +3
    Ждем, когда все это дело появится в хроме и сафари, тогда можно и первые опыты ставить ну и конечно nodejs там то точно можно будет не заботиться о совместимости. Фитча действительно удобная.
    Однако когда читаешь новые счецификации по ES хочется спросить у ребят, где они закупаются:
    особенно когда читаешь о перезагрузке операторов, переопределении typeof, всяких int32, int64, int32x4, int32x8
      +2
      Ждем, когда все это дело появится в хроме и сафари

      Уже сейчас можно использовать через трансляцию es6 -> es5

      особенно когда читаешь о перезагрузке операторов, переопределении typeof, всяких int32, int64, int32x4, int32x8

      Вышеперечисленного не будет, «int32, int64, int32x4, int32x8» предполагается только для определения StructType.

      Так что, не всё так плохо. Я, наоборот переживаю, что в es6 вошло так мало новых возможностей.
        0
        Так трансляция это не интересно, её можно было бы использовать и 10 лет назад, а можно написать свой транслятор, который будет делать все что угодно. Об этом никто не спорит. но интересна же нативная поддержка.

        Лично мне кажется новые фишки должны вводиться очень аккуратно, щас все идет в сторону усложенения, и читаемость кода падает как по мне. Вот смотрю я на эту презентацию www.slideshare.net/BrendanEich/value-objects2 и думаю, появиться все это и как жить?
          0
          > www.slideshare.net/BrendanEich/value-objects2
          сильно сомневаюсь, что такое когда-нибудь попадёт в стандарт ecmascript.

          А что касается трансляции, тут важно понимать, что несмотря на наличие CoffeeScript, LifeScript и подобных, это всё-таки были не стандарты. А ecmascript 6 — это стандарт. Однако, вопрос об отличии стандарта от свободных поделок это тема отдельной дискуссии. Я надеюсь, что вы меня поняли.

          Кроме того, используя трансляцию сейчас, вы в будущем сможете просто отключить её для браузеров которые поддерживают es6.
      +8
      Глядя на синтаксис хочется плакать.
      Не нашел каких-то особых плюсов использования стрелочных функций перед обычными.
        +3
        НУ почему же? очень подходит для колбэков когда там 1 строчка кода не городить столько лишних символов
          0
          Обычно в колбэках важен контекст.
            0
            Arrow functions обладают следующими преимуществами:
            * сохранение контекста
            * короткий синтаксис
            * оптимизированное выполнение js-движками
            * сохранение super (на данный момент не так актуально)

            По моему, вполне достойно.
              +2
              * сохранение контекста — согласен, это плюс
              * короткий синтаксис — посмотрите на последний скриншот в посте — от такого короткого синтаксиса слёзы наворачиваются
              * оптимизированное выполнение js-движками — кроме оптимизации this не увидел в статье никаких других оптимизаций

              Мне кажется, достаточно было добавить к текущему синтаксису сахар в виде удобного сохранения контекста и не городить новый синтаксис
                +1
                * короткий синтаксис — посмотрите на последний скриншот в посте — от такого короткого синтаксиса слёзы наворачиваются

                Ну это же я специально навернул, для привлечения внимания. За такой код обычно по рукам бьют в приличном обществе.
                * оптимизированное выполнение js-движками — кроме оптимизации this не увидел в статье никаких других оптимизаций

                Оптимизация проводится за счет следующих особенностей:
                1. Arrow function нельзя использовать в качестве конструктора
                2. Переменные this, arguments и super берутся от родительского function scope
                3. Внутри arrow function нельзя использовать «собственный» объект arguments — а это означает, что не надо синхронизировать значения аргументов и псевдо-массива arguments
                4. Функции call, apply и bind не могу сменить контекст
                  0
                  Ладно, я не собирался никого переубеждать. Это моё личное мнение.
                  Вот пункт 4 смущает немного: call, apply и bind не могут сменить контекст молча или покажут какую-то ошибку?
                    0
                    молча
                      +1
                      Это плохо.
                        0
                        Согласен с вами, но разработчики стандарта сошлись на том, что в этом плане работа должна быть аналогична функции у которой был закреплён контекст с помощью .bind
                  0
                  короткий синтаксис — посмотрите на последний скриншот в посте — от такого короткого синтаксиса слёзы наворачиваются


                  В статье вообще какое-то форматирование кода странное — то запятая в начале строки, то => переносится на другую строку. Интересно, это внутри компании такой styleguide.
                    0
                    Запятая в начале строки — это довольно известный code style, которым я пользуюсь в своих личных проектах.
                    Картинки в начале и конце — не более чем шутка.
                    Код функции `idGen` предваряется зачеркнутым саркастическим словосочетанием, что, по замыслу, должно было настроить на шутливый тон.
                    0
                    Это верно, если забить на обратную совместимость. К примеру для callback-функци jQuery обычное дело использовать в качестве this — элемент, который вызвал событие.
                      +1
                      и обычное дело как раз таки мешать такому поведению, ибо когда вы работаете в ооп видеть при ивенте в колбеке сам элемент — ужасно. Вы навешиваете событие и внутри хотите работать с инстансом своего класса, а уж элемент лучше получать из ивента.

                      Не одним JQ едины и там далеко не лучшая реализация такого поведения она не применима для больших проектов, а простые слайдеры писать надо далеко не всем. Тот же backbone успешно передает правильный контекст в коллбеки к события и жизни становится простой и удобной
                        0
                        А я не говорил, что это хорошая практика. Я говорю о том, что обратная совместимость является приоритетной при разработке новых стандартов JS.
                          +1
                          А где же тут обратная совместимость?
                      0
                      Так а bind уже и так есть.
                        0
                        Он довольно медленный
                          0
                          А есть ссылка на какой-нибудь тест, посмотреть на сколько?
              +8
              Для меня только улучшение читабельности при рутинных операциях с масивами и передача «правильного» this без bind уже дотаточно.
                +1
                Нормальный такой синтаксис, как во всех приличных домах.
                Преимущества — лаконичность и захват this, больше никаких.

                Кстати, они развернули грабли другой стороной — как теперь получить this и arguments места вызова? Писать old-style анонимную функцию и без вариантов?
                  0
                  > получить this и arguments места вызова
                  Я не совсем понял вопрос.

                  this будет такой, каким он был в момент создания arrow function.
                  А переменное число параметров реализуется через rest

                  Я ответил на ваш вопрос?
                    0
                    rest — да, это я проглядел.
                    а this… я даже не знаю, когда вообще может понадобиться this контекста вызова, а не контекста создания функции, но сам факт невозможности его получить меня печалит.
                      0
                      Невозможность получить this лишь мешает нам нафигачит методы вот в таком стиле (а то многие бы покусились) а также помогает разработчиком интерпретатора оптимизировать скорость таких функций. Я вижу только плюсы.
                        –3
                        а в JQuery-хэндлерах лазить на каждую мелочь в Event.currentTarget? Мне как-то не по нраву.
                          +2
                          Я вам еще раз повторю, в вашем плагинчике для слйдера — все ок, ничего более не надо. Если у вас ООП код большого приложения то предполагается что при клике по кнопочке вы будите юзать не $(this).fadeIn(), а работать с конкретным инстансом класса и вызывать его методы и тут вам надо чтобы this был не текущий объетк дома, а конктекст вашего приложения.
                +1
                Всё это замечательно, вкусно, жду их много лет, но от проблемы биндинга это избавляет лишь частично, когда нужно передать анонимную функцию с сохранением контекста.
                Методы объекта нельзя привязывать к нему же, в его нотации. Методы прототипа «класса» придется привязывать так же, в конструкторе, как это делается в CoffeeScript.
                В итоге, в большинстве случаев мы имеем всё то же — foo.bar.baz.bind(foo.bar).
                Проблему бы решил оператор привязки контекста, например в LiveScript это foo.bar~baz.
                Либо метод биндинга в прототипе Object, аналогичный функции bindKey из LoDash.
                И не говорите, что добавление свойства в прототип Object — зло, их там и так уже расплодилось…
                Скрытый текст
                Object.prototype.constructor
                Object.prototype.hasOwnProperty()
                Object.prototype.isPrototypeOf()
                Object.prototype.propertyIsEnumerable()
                Object.prototype.toLocaleString()
                Object.prototype.toString()
                Object.prototype.valueOf()
                Object.prototype.__proto__
                Object.prototype.__count__
                Object.prototype.__noSuchMethod__
                Object.prototype.__parent__
                Object.prototype.__defineGetter__()
                Object.prototype.__defineSetter__()
                Object.prototype.__lookupGetter__()
                Object.prototype.__lookupSetter__()
                Object.prototype.eval()
                Object.prototype.toSource()
                Object.prototype.unwatch()
                Object.prototype.watch()

                В самом примитивном виде это выглядит так:
                Object.defineProperty(Object.prototype, 'tie', {
                  value: function(key){
                    var that = this
                      , fn   = that[key];
                    return function(){
                      return fn.apply(that, arguments);
                    }
                  }
                });
                

                В итоге, вместо foo.bar.baz.bind(foo.bar) мы получим foo.bar.tie('baz').
                Или, например,
                var log = console.tie('log'); // вместо console.log.bind(console);
                log(42); // -> 42
                

                Правда, до свидания IE 8-.
                  +1
                  Как активный пользователь Google Closure Compiler в Anvanced mode, я не могу спокойно смотреть на код в котором смешаны скобочная (['name']) и точечная(.name) нотации. После GCC такой код перестанет работать.

                  Ещё один довод — это поддержка в IDE, которым очень сложно анализировать код типа `console.tie('log')`.

                  Но, в целом, я с вами полностью согласен — описанную вами проблему стрелочные функции не решают.
                  В частном же случае, лично я никогда не испытывал проблем с методами класса. А обработчики DOM-событий, прекрасно пишутся используя handleEvent и не теряют контекст.
                    0
                    К стати, вам наверняка будет интересна вот эта ветка дискуссии Merging Bind Syntax with Relationships в которой как раз обсуждают нужный вам оператор. К сожалению, этот вопрос был поднят слишком поздно и в es6 этот оператор, скорее всего, не попадёт.
                    Вот пример:
                    // Using a function as an extension method:
                    function f() { return this.x; }
                    
                    obj.x = "abc";
                    obj::f(); // "abc";
                    
                      +1
                      Я тоже не особый любитель смешивать точечную и скобочную нотации, но за неимением лучшего и из-за явного нарушения принципа DRY в foo.bar.baz.bind(foo.bar) не отказался бы от подобного метода в стандартной библиотеке языка. Жму код uglify с максимально агрессивными параметрами, никаких проблем с подобным не возникает, если у GCC проблемы с подобным — сочувствую его пользователям :)

                      Обсуждения читаю регулярно, в чуть более приятном формате, данное предложение видел, занятная штука, но это немного другое :) Вроде раньше что-то более похожее проскакивало.

                      Вот еще вариант на базе Proxy, но более тяжелый.
                        0
                        > Жму код uglify с максимально агрессивными параметрами
                        GCC даже в simple mode намного агресивнее uglify. И пользователи GCC, в основном, знают об этом.

                        > занятная штука, но это немного другое
                        Объясните пожалуйста, чем вас не устраивает данное предложение? Я от него просто в восторге.
                          0
                          А объясните плиз, зачем вам вообще сжатие?.. Экономия не так чтобы совсем драматическая (если у вас код не весит конечно мегабайт 5-6), каналы сейчас у всех толстый стали. Экономия на спичках и уменьшение читаемости для тех, кто захочет ваш код посмотреть в отладчике. Или для сокрытия от посторонних глаз и делается? :)
                          0
                          Вот только сейчас подумал, что приведённый вами пример можно записать очень лаконично на es6:
                           foo.bar.baz.bind(...[])
                          

                          Единственный тут недостаток — это пустой массив, но к нему можно привыкнуть.
                            +1
                            Уж думал плохо rest / spread из ES6 понимаю, а нет — не работает. Данное выражение привяжет как контекст undefined, без strict mode он будет преобразован в глобальный объект (window).

                            А по поводу оператора — ничего против не имею, интересная штука, но больно глобальная, появление — маловероятно, обсуждения никакого.
                              0
                              Да, вы правы. Я поторопился и не проверил
                          0
                          А чем данный пример по поведению будет отличаться от
                          f.call(obj)
                          

                          Не очень понял просто.
                        0
                        Больше всего интересует сохранение this. Насколько я понял из статьи, стрелочная нотация берёт this из текущего окружения. Не совсем понятно, каким образом можно лаконично подобный код насильно привязать к объекту:

                        var MyClass = function(){ this.init.apply( this, arguments ); };
                        MyClass.prototype =
                        {
                          init: function(){},
                          some1: function(){},
                          some2: function(){},
                        }


                        Если я опишу его как:
                        var MyClass = function(){ this.init.apply( this, arguments ); };
                        MyClass.prototype =
                        {
                          init: function(){},
                          some1: () => { /* ... */ },
                          some1: () => { /* ... */ },
                        }
                        

                        то, судя по статье, some1, some2, init будут вызываться с this === window. Получается о5 потребуются какие то обёртки или прочие шаманства?
                          0
                          Выше я написал, что arrow functions не решают эту проблему. Однако, не только вы заметили столь серьёзную недоработку и люди обсуждают возможность ввести оператор :: для решения описанной вами проблемы, смотрите комментарий.

                          Хотя, в коде который вы приводите, закреплять this не нужно. Скорее вам нужна более лаконичная запись функций (я прав?). Ваш код можно переписать на es6, используя т.н. shorthand:
                          var MyClass = function(){ this.init.apply( this, arguments ); };
                          MyClass.prototype =
                          {
                            init: function(){},
                            some1() { /* ... */ },
                            some1() { /* ... */ },
                          }
                          

                          а если ещё использовать и остальные фичи es6, тогда всё совсем хорошо будет:

                          class MyClass{
                            constructor(...rest) {
                              this.init(...rest);
                            }
                            
                            init(){ /**/ }
                            some1() { /* ... */ }
                            some1() { /* ... */ }
                          }
                          
                            0
                            Не совсем понял ваш комментарий. Я бы хотел избавиться от всевозможных

                            this.$dom_obj.click( this.someFuncton.bind( this ) );

                            и прочих применений .bind, только ради того, чтобы внутри someFunction не потерять this. Сейчас используя nodeJS мне приходится вызывать .bind даже у генераторов, если я передаю их в какую-нибудь внешнюю функцию. Это один из самых неприятных моментов для меня в JS (второй это невозможность передать что-нибудь по указателю или ссылке, если это не объект).
                              0
                              К сожалению, стрелочные функции это не панацея и не помогут в приведённом вами случае. Чтобы было лучше понятно, можно относится к стрелочным функциям не как к функциям, а как к блокам — то есть стрелочные функции полезны только в рамках того же контекста, в котором были созданы.

                              В случае же кода this.$dom_obj.click( this.someFuncton.bind( this ) ); придётся всё также использовать .bind либо, вы можете воспользоваться волшебным handleEvent, о нём вы можете почитать в моей недописанной статье, либо в англоязычных источниках
                                0
                                А можно создать стрелочную функцию внутри конструктора?

                                class MyClass{
                                  constructor(...) {
                                    this.myfunc_pow = (x) => {return x*x};
                                  }
                                }
                                


                                Если я правильно понимаю, таким образом мы привяжем эту функцию к данному объекту вне зависимости откуда она будет вызвана.
                                  0
                                  Да, конечно
                          0
                          может кто-нибудь подсказать название цветовой схемы, которая на картинке?
                            0
                            Monokai, включена по умолчанию в Sublime Text 2.
                              0
                              благодарю
                            +1
                            Про this все понятно и здорово. А можете пояснить, зачем они сохраняют arguments контекста?
                              +1
                              Нужно было «облегчить» тело стрелочной функции. В первоначальном варианте просто запрещалось использование arguments внутри стрелочной функции. Позже ограничение смягчили и теперь arguments закрепляется вместе с this и super.

                              Стоит заметить, что в es6, в принципе, рекомендуется не использовать arguments — в классических функциях его поддержка оставлена только для обратной совместимости.
                              0
                              Употреблять стрелочные функции совместно с jQuery надо будет с превеликой осторожностью, так как jQuery подменяет this-контекст классических функций, однако, по-видимому, будет обламываться насчёт this-контекста стрелочных функций.

                              То есть смотрю я, например, на некоторые свои скрипты и вижу: вздумай я перейти на употребление стрелочных функций, меня ждало бы ошибочное действие буквально на второй из значимых строк кода.
                                0
                                (В том смысле, что если в этой строке заменить классическую функцию на стрелочную, то тогда на следующей же строке значение this будет несколько неожиданным.)
                                  +2
                                  Стрелочные функции решают определённый пласт задач, в приведённом вами месте стрелочным функциям не место. То есть, это всё равно что написать: «не стоит бездумно заменять все классические функции на стрелочные» и быть безусловно правым.
                                    +2
                                    На мой взгляд, это не самая лучшая особенность jQuery, имхо. Всегда использую .each с двумя аргументами, т.к. для меня сохранить this текущего — класс-объекта куда важнее, чем сэкономить 30 символов. Приходится писать нечто вроде:

                                    $list.each( $.proxy( function( ind, item )
                                    {
                                      ...
                                    }, this ) );
                                    

                                    практичеки всегда
                                    +1
                                    Когда стрелочные функции без перекомпиляции можно будет пользовать для написания скриптов, которые будут исполняться в более чем 1 браузере, потребность в jquery в её нынешнем виде врятли будет.
                                    В этом светлом будущем jquery разве что будет абстрагировать от каких-нить вендорных приблуд IE25 \ ФФ100500 \ Хроме 6666666
                                      0
                                      Не совсем понимаю, а как стрелочные функции сильно помешают jQuery? Ну, то есть, многие используют jquery чисто из-за того что писать $('.class') куда удобнее чем document.getElementsByClassName('class'). Как тут помогут стрелочные функции?
                                        0
                                        Да забей, момент был написан для сбора плюса)
                                        jQuery — сахар, стрелочные функции — сахар. кто-то должен уйти.
                                    –2
                                    <зануда>
                                    var result = values.sort((a, b) => a - b);

                                    Даже если массив полон значений, разность которых будет давать -1, 0 или 1, данный код всё равно вызывает некоторые опасения.
                                    </зануда>
                                      +2
                                      А коллбек не обязан возвращать строго -1, 0, 1:
                                      If comparefn is not undefined, it should be a function that accepts two arguments x and y and returns a negative value if x < y, zero if x = y, or a positive value if x > y.

                                      www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.11 (выделение мое).
                                      +1
                                      В TypeScript почти такие же arrow functions. Только arguments доступен внутри все-таки. Остальное точь-в-точь.

                                      Only users with full accounts can post comments. Log in, please.