Стрелочные функции в серии ES6

внешний интерфейс JavaScript React.js Immutable.js
Стрелочные функции в серии ES6

обзор

Давайте начнем с обзора основного синтаксиса функции стрелки вниз.

ES6 добавляет стрелочные функции:

let func = value => value;

эквивалентно:

let func = function (value) {
    return value;
};

Если вам нужно передать несколько параметров в функцию:

let func = (value, num) => value * num;

Если блок кода функции требует нескольких операторов:

let func = (value, num) => {
    return value * num
};

Если вам нужно вернуть объект напрямую:

let func = (value, num) => ({total: value * num});

В сочетании с переменной деструктуризацией:

let func = ({value, num}) => ({total: value * num})

// 使用
var result = func({
    value: 10,
    num: 10
})

console.log(result); // {total: 100}

Много раз вы можете не подумать об использовании этого, поэтому давайте возьмем пример.Например, при техническом выборе React и Immutable мы будем делать это при работе с событием:

handleEvent = () => {
  this.setState({
    data: this.state.data.set("key", "value")
  })
};

На самом деле, это можно упростить до:

handleEvent = () => {
  this.setState(({data}) => ({
    data: data.set("key", "value")
  }))
};

сравнивать

В этой статье мы сосредоточимся на сравнении стрелочных функций и обычных функций.

Ключевые отличия включают в себя:

1. без этого

В стрелочных функциях этого нет, поэтому его значение нужно определять, просматривая цепочку областей видимости.

Это означает, что если стрелочная функция содержится в нестрелочной функции, она привязывается к this ближайшей нестрелочной функции.

Чтобы смоделировать реальный пример разработки:

Наше требование — нажать кнопку и изменить цвет фона кнопки.

Чтобы облегчить разработку, мы извлекаем компонент Button, а когда его нужно использовать, напрямую:

// 传入元素 id 值即可绑定该元素点击时改变背景色的事件
new Button("button")

HTML-код выглядит следующим образом:

<button id="button">点击变色</button>

Код JavaScript выглядит следующим образом:

function Button(id) {
    this.element = document.querySelector("#" + id);
    this.bindEvent();
}

Button.prototype.bindEvent = function() {
    this.element.addEventListener("click", this.setBgColor, false);
};

Button.prototype.setBgColor = function() {
    this.element.style.backgroundColor = '#1abc9c'
};

var button = new Button("button");

Вроде проблем нет, но результат - ошибкаUncaught TypeError: Cannot read property 'style' of undefined

Это связано с тем, что при регистрации события для элемента с помощью addEventListener() значение this в функции события является ссылкой на элемент.

Итак, если мы находимся в setBgColorconsole.log(this), это указывает на элемент кнопки, тогда this.element не определен, и естественно сообщить об ошибке.

Вы можете спросить, поскольку все это указывает на элемент кнопки, тогда мы напрямую изменим функцию setBgColor на:

Button.prototype.setBgColor = function() {
    this.style.backgroundColor = '#1abc9c'
};

Не можете решить эту проблему?

Это действительно возможно сделать, но в реальной разработке мы можем вызывать другие функции в setBgColor, например, написав это:

Button.prototype.setBgColor = function() {
    this.setElementColor();
    this.setOtherElementColor();
};

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

С ES5 мы обычно делаем это:

Button.prototype.bindEvent = function() {
    this.element.addEventListener("click", this.setBgColor.bind(this), false);
};

Чтобы избежать влияния addEventListener, используйте привязку, чтобы заставить this из setBgColor() быть объектом экземпляра.

С ES6 мы можем решить эту проблему лучше:

Button.prototype.bindEvent = function() {
    this.element.addEventListener("click", event => this.setBgColor(event), false);
};

Так как у стрелочной функции this нет, то она будет искать значение this во внешнем слое, то есть this в bindEvent.В это время this указывает на объект экземпляра, поэтому метод this.setBgColor может быть вызван корректно , и this в this.setBgColor также будет правильно указывать на экземпляр объекта.

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

Наконец, поскольку в стрелочных функциях этого нет, вы не можете использовать call(), apply(), bind(), чтобы изменить точку this. Вы можете увидеть пример:

var value = 1;
var result = (() => this.value).bind({value: 2})();
console.log(result); // 1

2. Никаких аргументов

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

function constant() {
    return () => arguments[0]
}

var result = constant(1);
console.log(result()); // 1

Что, если мы просто хотим получить доступ к параметрам стрелочной функции?

Вы можете получить доступ к параметрам как к именованным параметрам или остальным параметрам:

let nums = (...nums) => nums;

3. Нельзя вызывать с новым ключевым словом

Функции JavaScript имеют два внутренних метода: [[Call]] и [[Construct]].

Когда функция вызывается через new, выполняется метод [[Construct]], создается объект экземпляра, а затем выполняется тело функции, привязывая его к экземпляру.

При прямом вызове выполняется метод [[Call]] и тело функции.

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

var Foo = () => {};
var foo = new Foo(); // TypeError: Foo is not a constructor

4. Нет новой.цели

Также нет значения new.target, так как его нельзя вызвать с помощью new.

Для new.target вы можете обратиться кГолодание 6. Жуань Ифэн.com/#docs/class…

5. Нет прототипа

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

var Foo = () => {};
console.log(Foo.prototype); // undefined

6. Нет супер

Прототипа нет, и естественно через super нельзя обратиться к свойствам прототипа, поэтому у стрелочных функций тоже нет super, а вот так, аргументы, и new.target, эти значения определяются ближайшим не стрелочным функционировать на периферии.

Суммировать

Наконец, о стрелочных функциях, введение в MDN:

An arrow function expression has a shorter syntax than a function expression and does not have its own this, arguments, super, or new.target. These function expressions are best suited for non-method functions, and they cannot be used as constructors.

Это переводится как:

Выражения стрелочных функций имеют более короткий синтаксис, чем выражения функций, и не связывают собственные this, arguments, super или new.target. Эти функциональные выражения лучше всего использовать для функций, не являющихся методами, и их нельзя использовать в качестве конструкторов.

Так что же такое функции, не являющиеся методами?

Давайте сначала посмотрим на определение метода:

A method is a function which is a property of an object.

Функции в свойствах объекта называются методами, поэтому не-метод относится к функциям, которые не используются в качестве свойств объекта, но почему стрелочная функция больше подходит для не-метода?

Давайте посмотрим на пример, чтобы понять:

var obj = {
  i: 10,
  b: () => console.log(this.i, this),
  c: function() {
    console.log( this.i, this)
  }
}
obj.b();
// undefined Window
obj.c();
// 10, Object {...}

самовыполняющаяся функция

Форма самовыполняющейся функции:

(function(){
    console.log(1)
})()

или

(function(){
    console.log(1)
}())

Используйте стрелки для упрощения написания самовыполняющихся функций:

(() => {
    console.log(1)
})()

Но обратите внимание: использование следующего способа написания сообщит об ошибке:

(() => {
    console.log(1)
}())

Почему он сообщает об ошибке? Привет, если знаешь, дай мне знать~

серия ES6

Адрес каталога серии ES6:GitHub.com/ в настоящее время имеет бриз…

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

Если есть какие-либо ошибки или неточности, пожалуйста, поправьте меня, большое спасибо. Если вам нравится или у вас есть вдохновение, добро пожаловать в звезду, что также является поощрением для автора.