В ES6 есть новый способ создания функций - С помощью оператора Стрелка
Первое, что мы сделаем, это запустим скрипт Babel, который будет следить за файлами и при их изменении создавать свежие версии.
Откроем папку проекта в командной строке (КС). Вводим команду:
И нажать Enter
В папке src создадим файл arr.js и сразу укажу его в файле index.html
Последние версии браузеров поддерживают стрелочные функции без транспиляции и мой браузер входит в их число.
Давайте напишем функцию, которая складывает два числа и возвращает их сумму. Назовем функцию add.
В консоли мы увидим результат -
Теперь, давайте переведем эту функцию стрелочную.
Уберем слово function, уберем имя функции и уберем фигурные скобки, и слово -
Если посмтреть на тип переменной add используя оператор typeof:
То мы увидим в консоли
Это означает что стрелочные функции это обычные функции. И в этом можно убедиться посмотрев на транспилированный код.
Мы видим, что Babel превратил наш код в простое выражение функцией.
Давайте напишем простую функцию которая будет возводить заданное число в квадрат.
Посмотрим в консоли:
Стрелочная функция будет выглядеть вот так:
Эта функция просто выводит в консоль число 33. Стрелочная:
Создадим функцию которая не будет возвращать ничего. Она просто выведет сообщение в консоль браузера.
Стрелочная:
Создадим функцию тело которой будет состоять из двух строк.
Функция будет принимать два параметра. Теле функции создадим переменную. После этого вернём результат.
Стрелочная:
Теперь создадим функцию, которая возвращает литерал объекта:
В консоли мы увидим:
Теперь попробуем создать стрелочную функцию, которая будет возвращать литерал объекта.
Стрелочная функция возвращающая литерал объекта:
Теперь попробуем использовать стрелочную функцию в качестве IIFE - Immediately-invoked function expression
Если сказать коротко, то это функция, которая выполняется сразу после объявления
Это выглядит вот так:
Стрелочная IIFE - функция будет выглядеть вот так:
Её нельзя просто так взять и спустить на строку ниже. Выдаст ошибку!
Давайте создадим массив с некоторыми числами и назовем его
Давайте вы считаем сумму всех переменных массива. Для этого я объявлю еще одну переменную -
Воспользуемся методом
В консоли мы увидим
Таким образом, то что у нас ранее занимало три строки, теперь занимает одну.
Также мы можем возвести в квадрат каждый элемент массива.
Далее посмотрим как стрелочные функции работают с объектами.
У объекта person будет свойство
В консоли браузера мы увидим приветствие и сам объект person.
Теперь мы заменим функцию на стрелочную и посмотрим, что произойдет с this.
Убрали слово
Теперь мы не получили значение имени и в качестве значения
Но почему? Дело в том, что значение
У нас есть программа.
В ней пока что кроме объекта window ничего нет. Добавили объект person. Заметьте, что у метода мы используем стрелочную функцию. Как мы и говорили - значение
Если мы рассмотрим обычную функцию, то мы знаем, что
Представим, что наш Bob достаточно занятой и ему нужно пара секунд, чтобы завершить свою работу. Ожидание в 2 сек. мы симулируем с помощью функции
Если у вас есть опыт работы с JavaScript, то я думаю, что вы понимаете в чем заключается проблема. Все равно, давайте посмотрим на то, что будет в браузере. Ровно две секунды спустя мы увидим в браузере такую картину.
Но почему? Если посмотреть наш код, то логично предположить. что
Теперь благодаря замыканию Функция которую мы отправляем в
Можно для наглядности посмотреть на то, что ссылаются наши
В консоли мы увидим подтверждение:
Мы видим, что
В ES6 для решения этой проблемы мы можем просто использовать стрелочную функцию.
В результате мы в консоли увидим:
В графическом примере для стрелочной функции контекстом будет служить объект person, а не объект window. именно поэтому
Помимо компактного синтаксиса, стрелочные функции были введены для решения таких вот проблем.
В качестве ознакомления, вы можете посмотреть как решил это Babel
Думаю, что самое трудное в этой части - это понять как работают замыкания.
Еще некоторые особенности стрелочных функций:
=>
. Такие функции называются стрелочные. Они предлагают более компактный синтаксис. Они не имеют имени и они по-своему работают с this
.
Все материалы по ES6
Первое, что мы сделаем, это запустим скрипт Babel, который будет следить за файлами и при их изменении создавать свежие версии.
Откроем папку проекта в командной строке (КС). Вводим команду:
npm run watch
И нажать Enter
В папке src создадим файл arr.js и сразу укажу его в файле index.html
<script src="src/arr.js"></script>
Последние версии браузеров поддерживают стрелочные функции без транспиляции и мой браузер входит в их число.
Давайте напишем функцию, которая складывает два числа и возвращает их сумму. Назовем функцию add.
function add ( x, y ) { return x + y; } console.log ( add (3, 6 ));
В консоли мы увидим результат -
9
Теперь, давайте переведем эту функцию стрелочную.
Уберем слово function, уберем имя функции и уберем фигурные скобки, и слово -
return
. После параметров поставим стрелку.
let add = ( x, y ) => x + y; console.log ( add (4, 6 ));
Если посмтреть на тип переменной add используя оператор typeof:
console.log(typeof(add));
То мы увидим в консоли
function
Это означает что стрелочные функции это обычные функции. И в этом можно убедиться посмотрев на транспилированный код.
"use strict";
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
var add = function add(x, y) {
return x + y;
};
console.log(add(4, 6));
console.log(typeof add === "undefined" ? "undefined" : _typeof(add));
Мы видим, что Babel превратил наш код в простое выражение функцией.
Давайте напишем простую функцию которая будет возводить заданное число в квадрат.
let add = ( x, y ) => x + y;
console.log ( add (4, 6 ));
console.log(typeof(add));
let square = function( a ) {
return a * a;
}
console.log( square ( 4 ));
Посмотрим в консоли:
Стрелочная функция будет выглядеть вот так:
let square = x => x * x;
Если стрелочная функция принимает только один параметр, то нет необходимости заключать его в скобки!
Давайте напишем функцию которая вообще не принимает параметров.
function givNumer () { return 33; } console.log( givNumer ());
Эта функция просто выводит в консоль число 33. Стрелочная:
let givNumer = () => 33; console.log( givNumer ());
Создадим функцию которая не будет возвращать ничего. Она просто выведет сообщение в консоль браузера.
let log = function () { console.log( 'Hello World!' ); }; log();
Стрелочная:
let log = () => console.log('Hello World!!!'); log();
Создадим функцию тело которой будет состоять из двух строк.
Функция будет принимать два параметра. Теле функции создадим переменную. После этого вернём результат.
let mult = function ( a, b ) { let result = a * b; return result; } console.log( mult ( 4, 5 ));
Если в стрелочной функции несколько строк, то фигурные скобки -
{}
обязательны! И обязательно определить то, что возвращает эта функция, используя ключевое слово return
Стрелочная:
let mult = ( a, b ) => { let result = a * b; return result; } console.log( mult (4, 5 ));
Теперь создадим функцию, которая возвращает литерал объекта:
let literal = function () { return { name : 'John'}; } console.log ( literal () );
В консоли мы увидим:
Теперь попробуем создать стрелочную функцию, которая будет возвращать литерал объекта.
Следует помнить, что если стрелочная функция возвращает литерал объекта, то нужны круглые скобки -
()
Стрелочная функция возвращающая литерал объекта:
let literal = () => ( { name : 'John'} ); console.log ( literal () );
Теперь попробуем использовать стрелочную функцию в качестве IIFE - Immediately-invoked function expression
Если сказать коротко, то это функция, которая выполняется сразу после объявления
Это выглядит вот так:
( function () { console.log('IIFE'); })();
Стрелочная IIFE - функция будет выглядеть вот так:
( () => console.log('IIFE'))();
Важной особенностью стрелочных функций является то, что стрелка должна идти сразу после параметров!
Её нельзя просто так взять и спустить на строку ниже. Выдаст ошибку!
Практическое применение стрелочных функций.
Стрелочные функции очень удобно применять с массивами.Давайте создадим массив с некоторыми числами и назовем его
numbers
. Я думаю что вы знаете, что у массивов есть полезные методы, которые позволяют это массив перебирать, фильтровать и т.д.
Давайте вы считаем сумму всех переменных массива. Для этого я объявлю еще одну переменную -
let sum = 0;
Воспользуемся методом
forEach()
который есть у каждого массива, мы переберем элементы и прибавим к сумме.
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; let sum = 0; numbers.forEach( function( num ) { sum += num; }); console.log ( sum );
В консоли мы увидим
55
.
Давайте превратим эту функцию в стрелочную:
numbers.forEach( num => sum += num ); console.log(sum);
Таким образом, то что у нас ранее занимало три строки, теперь занимает одну.
Также мы можем возвести в квадрат каждый элемент массива.
let squared = numbers.map( n => n * n ); console.log ( squared );
Далее посмотрим как стрелочные функции работают с объектами.
Стрелочные функции и this.
Для этого я создам литерал объекта который сохраню в переменную рerson.У объекта person будет свойство
name
со значением ‘Bob’
и свойства greet
- поприветствовать.В консоль выведем приветствие также посмотрим назначение this
.
let person = { name: 'Bob', greet: function () { console.log( 'Hello! My name is ' + this.name ); console.log( this ); } }; person.greet();
В консоли браузера мы увидим приветствие и сам объект person.
Теперь мы заменим функцию на стрелочную и посмотрим, что произойдет с this.
Убрали слово
function
и добавили =>
.
let person = { name: 'Bob', greet: () => { console.log( 'Hello! My name is ' + this.name ); console.log( this ); } }; person.greet();
Теперь мы не получили значение имени и в качестве значения
this
- window
!
Но почему? Дело в том, что значение
this
берется из контекста в котором функция объявлена.! Независимо от того, где эта функция будет выполнена. Это можно увидеть на картинке:
У нас есть программа.
В ней пока что кроме объекта window ничего нет. Добавили объект person. Заметьте, что у метода мы используем стрелочную функцию. Как мы и говорили - значение
this
будет браться из контекста. Контекст это окружение. В данном случае окружением объекта person
, всех его свойств и методов, будет являться объект window
. И если значение this
будет браться из контекста, то this
будет ссылаться на объект window
.
Если мы рассмотрим обычную функцию, то мы знаем, что
this
ссылается на сам объект person
.
Вы можете спросить, почему значение this
в стрелочных функциях берется из контекста?
А ответ очень простой - их так сделали! :-)
Дело в том, что стрелочные функции были созданы для решения проблем в другой ситуации.
Давайте посмотрим на примере.
Для того, чтобы увидеть проблему мы вернемся к нашей стрелочной функции.
let person = { name: 'Bob', greet: function () { console.log( 'Hello! My name is ' + this.name ); console.log( this ); } };
Представим, что наш Bob достаточно занятой и ему нужно пара секунд, чтобы завершить свою работу. Ожидание в 2 сек. мы симулируем с помощью функции
setTimeout();
.В качестве первого параметра эта функция принимает функцию и вторым параметром - количество миллисекунд, которые необходимо подождать.
let person = { name: 'Bob', greet: function () { setTimeout( function () { console.log( 'Hello! My name is ' + this.name ); console.log( this ); }, 2000); } }; person.greet();
Если у вас есть опыт работы с JavaScript, то я думаю, что вы понимаете в чем заключается проблема. Все равно, давайте посмотрим на то, что будет в браузере. Ровно две секунды спустя мы увидим в браузере такую картину.
Но почему? Если посмотреть наш код, то логично предположить. что
this
ссылается на объект person
, так как мы используем обычную функцию.
Дело в том, что setTimeout()
принадлежит объекту window
.
Если написать так: window.setTimeout()
, то как вы думаете на что ссылается thus
?
И в консоли мы получим тот же самый результат!
В ES5 есть несколько способов решить эту проблему. Мы рассмотрим самый распространенный:
Перед setTimeout()
я объявлю еще одну переменную that
и в качестве значения присвоим this
. И теперь, в теле функции вместо this
мы укажем that
.
let person = { name: 'Bob', greet: function () { let that = this; setTimeout( function () { console.log( 'Hello! My name is ' + that.name ); console.log( that ); }, 2000); } }; person.greet();
Теперь благодаря замыканию Функция которую мы отправляем в
setTimeout()
будет иметь доступ к переменной that
, значением которой будет this
, то есть, в данном случае, объект person
.
Можно для наглядности посмотреть на то, что ссылаются наши
that
и this
.
let person = { name: 'Bob', greet: function () { let that = this; setTimeout( function () { console.log( 'Hello! My name is ' + that.name ); console.log( 'It is my That = ' + that ); console.log( 'It is my This = ' + this ); }, 2000); } }; person.greet();
В консоли мы увидим подтверждение:
Мы видим, что
this
будет объектом окна - This = [object Window]
, а
that
будет объектом нашего person
- That = [object Object]
.
В ES6 для решения этой проблемы мы можем просто использовать стрелочную функцию.
let person = { name: 'Bob', greet: function () { setTimeout( () => { console.log( 'Hello! My name is ' + this.name ); console.log( 'It is my This = ' + this ); }, 2000); } }; person.greet();
В результате мы в консоли увидим:
В графическом примере для стрелочной функции контекстом будет служить объект person, а не объект window. именно поэтому
this
будет ссылаться на person.
Помимо компактного синтаксиса, стрелочные функции были введены для решения таких вот проблем.
В качестве ознакомления, вы можете посмотреть как решил это Babel
var person = { name: 'Bob', greet: function greet() { var _this = this; setTimeout(function () { console.log('Hello! My name is ' + _this.name); console.log('It is my This = ' + _this); }, 2000); } }; person.greet();Babel использовал тот же самый метод, что и мы в ES5. Вся разница в том, что мы называли переменную
that
, а Babel назвал - _this
. Благодаря замыканию, функция которую мы отправляем в setTimeout
, будет иметь доступ к переменной _this
и как следствие - к объекту person
.
Думаю, что самое трудное в этой части - это понять как работают замыкания.
Еще некоторые особенности стрелочных функций:
- Стрелочные функции нельзя использовать как конструкторы объектов. То есть с ними нельзя использовать оператор
new
. - Со стрелочными функциями нельзя использовать методы:
bind()
call()
apply()
Это происходит потому, что мы не можем изменить значение
Получим ошибку:
this
. Оно автоматически берется из контекста.
Комментариев нет:
Отправить комментарий