Недоволен другими ответами. Ответ, получивший наибольшее количество голосов от 13.03.2019, фактически неверен.
Краткая версия того, что =>
означает, - это ярлык, записывающий функцию И для привязки ее к текущему this
const foo = a => a * 2;
Фактически является ярлыком для
const foo = function(a) { return a * 2; }.bind(this);
Вы можете увидеть все, что было сокращено. Нам не нужны ни function
, ни return
, ни .bind(this)
, ни даже фигурные скобки или круглые скобки
Чуть более длинный пример стрелочной функции мог бы быть
const foo = (width, height) => {
const area = width * height;
return area;
};
Показывая, что если нам нужно несколько аргументов функции, нам нужны круглые скобки, а если мы хотим написать более одного выражения, нам нужны фигурные скобки и явный return
.
Важно понимать .bind
часть, и это большая тема. Это связано с тем, что this
означает в JavaScript.
ВСЕ функции имеют неявный параметр this
. Как this
устанавливается при вызове функции, зависит от того, как эта функция вызывается.
Брать
function foo() { console.log(this); }
Если вы назовете это нормально
function foo() { console.log(this); }
foo();
this
будет глобальным объектом.
Если вы в строгом режиме
`use strict`;
function foo() { console.log(this); }
foo();
// or
function foo() {
`use strict`;
console.log(this);
}
foo();
Будет undefined
Вы можете установить this
напрямую, используя call
или apply
function foo(msg) { console.log(msg, this); }
const obj1 = {abc: 123}
const obj2 = {def: 456}
foo.call(obj1, 'hello'); // prints Hello {abc: 123}
foo.apply(obj2, ['hi']); // prints Hi {def: 456}
Вы также можете установить this
неявно, используя оператор точки .
function foo(msg) { console.log(msg, this); }
const obj = {
abc: 123,
bar: foo,
}
obj.bar('Hola'); // prints Hola {abc:123, bar: f}
Проблема возникает, когда вы хотите использовать функцию в качестве обратного вызова или слушателя. Вы создаете класс и хотите назначить функцию в качестве обратного вызова, которая обращается к экземпляру класса.
class ShowName {
constructor(name, elem) {
this.name = name;
elem.addEventListener('click', function() {
console.log(this.name); // won't work
});
}
}
Приведенный выше код не будет работать, потому что, когда элемент запускает событие и вызывает функцию, значение this
не будет экземпляром класса.
Один из распространенных способов решить эту проблему - использовать .bind
class ShowName {
constructor(name, elem) {
this.name = name;
elem.addEventListener('click', function() {
console.log(this.name);
}.bind(this); // <=========== ADDED! ===========
}
}
Поскольку синтаксис стрелки делает то же самое, мы можем написать
class ShowName {
constructor(name, elem) {
this.name = name;
elem.addEventListener('click',() => {
console.log(this.name);
});
}
}
bind
эффективно создает новую функцию. Если бы bind
не существовало, вы могли бы сделать свой собственный вот так
function bind(functionToBind, valueToUseForThis) {
return function(...args) {
functionToBind.call(valueToUseForThis, ...args);
};
}
В более старом JavaScript без оператора распространения это было бы
function bind(functionToBind, valueToUseForThis) {
return function() {
functionToBind.apply(valueToUseForThis, arguments);
};
}
Для понимания этого кода требуется понимание замыканий, но краткая версия is bind
создает новую функцию, которая всегда вызывает исходную функцию со значением this
, которое было привязано к ней. Стрелочные функции делают то же самое, поскольку они являются ярлыком для bind(this)
person
gman
schedule
13.03.2019