Uploaded by toshaboss777

Ninja Squad - Become A Ninja With Angular 1.9 - 2017 1-27 ru (1)

advertisement
Подпишитесь на DeepL Pro и переводите документы большего объема.
Подробнее на www.DeepL.com/pro.
Стать
с
Станьте ниндзя с Angular
Отряд ниндзя
Оглавление
1. Введение ....................................................................................................................................................................1
2. Мягкое введение в ECMASCRIPT 6....................................................................................................................4
2.1. Транспойлеры..................................................................................................................................................4
2.2. пусть ....................................................................................................................................................................5
2.3. Константы .........................................................................................................................................................6
2.4. Создание объектов.........................................................................................................................................6
2.5. Задание на деструктуризацию .................................................................................................................7
2.6. Параметры и значения по умолчанию .................................................................................................9
2.7. Оператор на отдыхе.....................................................................................................................................11
2.8. Занятия.............................................................................................................................................................12
2.9. Обещания ........................................................................................................................................................14
2.10. Функции стрелок .......................................................................................................................................17
2.11. Наборы и карты ..........................................................................................................................................20
2.12. Шаблонные литералы..............................................................................................................................21
2.13. Модули ...........................................................................................................................................................21
2.14. Заключение..................................................................................................................................................23
3. Идти дальше ES6 ..................................................................................................................................................24
3.1. Динамические, статические и дополнительные типы................................................................24
3.2. Входит в TypeScript ......................................................................................................................................25
3.3. Практический пример с DI ......................................................................................................................25
4. Погружение в TypeScript ...................................................................................................................................28
4.1. Типы как в TypeScript .................................................................................................................................28
4.2. Enums ................................................................................................................................................................29
4.3. Типы возврата ...............................................................................................................................................29
4.4. Интерфейсы....................................................................................................................................................30
4.5. Дополнительные аргументы...................................................................................................................30
4.6. Функционирует как собственность ......................................................................................................31
4.7. Занятия.............................................................................................................................................................31
4.8. Работа с другими библиотеками ...........................................................................................................33
4.9. Декораторы .....................................................................................................................................................34
5. Чудесная страна Web-компонентов .............................................................................................................37
5.1. Смелый новый мир .....................................................................................................................................37
5.2. Нестандартные элементы ........................................................................................................................37
5.3. Теневой DOM ..................................................................................................................................................38
5.4. Шаблон .............................................................................................................................................................39
5.5. Импорт HTML.................................................................................................................................................40
5.6. Полимер и Х-тег ............................................................................................................................................40
6. Постижение философии Angular ...................................................................................................................43
7. От нуля к чему-то.................................................................................................................................................47
7.1. Разработка и создание приложения на TypeScript..........................................................................47
7.2. Наш первый компонент............................................................................................................................49
7.3. Наш первый модуль Angular ...................................................................................................................51
7.4. Загрузка приложения .................................................................................................................................53
7.5. От нуля к чему-то лучшему с помощью Angular CLI .....................................................................56
8. Синтаксис шаблонизатора...............................................................................................................................58
8.1. Интерполяция ...............................................................................................................................................58
8.2. Использование других компонентов в наших шаблонах...........................................................62
8.3. Привязка имущества ..................................................................................................................................63
8.4. События............................................................................................................................................................67
8.5. Выражения и утверждения......................................................................................................................70
8.6. Локальные переменные ............................................................................................................................70
8.7. Структурные директивы ...........................................................................................................................71
8.8. Другие директивы шаблонов ..................................................................................................................75
8.9. Канонический синтаксис .........................................................................................................................76
8.10. Резюме ............................................................................................................................................................76
9. Инъекция зависимостей...................................................................................................................................80
9.1. DI самостоятельно........................................................................................................................................80
9.2. Простота разработки ..................................................................................................................................80
9.3. Легко настраивается ...................................................................................................................................83
9.4. Другие типы провайдеров ........................................................................................................................88
9.5. Иерархические форсунки..........................................................................................................................89
9.6. ИР без типов ...................................................................................................................................................91
10. Услуги .....................................................................................................................................................................93
10.1. Титульная служба......................................................................................................................................93
10.2. Метасервис ...................................................................................................................................................93
10.3. Создание собственного сервиса ...........................................................................................................94
11. Трубы ......................................................................................................................................................................96
11.1. Крысолов .......................................................................................................................................................96
11.2. json ...................................................................................................................................................................96
11.3. нарезка ...........................................................................................................................................................97
11.4. прописные буквы.......................................................................................................................................99
11.5. строчные буквы........................................................................................................................................100
11.6. титульный лист........................................................................................................................................100
11.7. количество..................................................................................................................................................100
11.8. процент........................................................................................................................................................101
11.9. валюта ..........................................................................................................................................................101
11.10. дата..............................................................................................................................................................102
11.11. async............................................................................................................................................................102
11.12. Создание собственных труб ..............................................................................................................103
12. Реактивное программирование ................................................................................................................106
12.1. Позвони мне, может быть.....................................................................................................................106
12.2. Общие принципы ....................................................................................................................................106
12.3. RxJS.................................................................................................................................................................107
12.4. Реактивное программирование в Angular ....................................................................................109
13. Строительные компоненты и директивы.............................................................................................111
13.1. Введение......................................................................................................................................................111
13.2. Директивы ..................................................................................................................................................111
13.3. Компоненты...............................................................................................................................................122
14. Стимулирующие компоненты и капсулирование ............................................................................125
14.1. Отечественная стратегия .....................................................................................................................126
14.2. Эмулируемая стратегия ........................................................................................................................126
14.3. Нет стратегии ............................................................................................................................................127
14.4. Стилизация хоста.....................................................................................................................................127
15. Тестирование вашего приложения ..........................................................................................................128
15.1. Проблема поиска неисправностей заключается в том, что поиск неисправностей
возвращается .............................................................................................................................................128
15.2. Модульное тестирование......................................................................................................................128
15.3. Поддельные зависимости .....................................................................................................................134
15.4. Компоненты для тестирования..........................................................................................................136
15.5. Тестирование с использованием поддельных шаблонов, провайдеров... .......................139
15.6. Сквозные испытания (e2e) ...................................................................................................................141
16. Отправка и получение данных по протоколу HTTP..........................................................................143
16.1. Получение данных ..................................................................................................................................143
16.2. Преобразование данных .......................................................................................................................145
16.3. Дополнительные опции .......................................................................................................................146
16.4. Jsonp ..............................................................................................................................................................147
16.5. Перехватчики............................................................................................................................................147
16.6. Тесты .............................................................................................................................................................149
17. Маршрутизатор ................................................................................................................................................151
17.1. Маршрут......................................................................................................................................................151
17.2. Навигация...................................................................................................................................................153
17.3. Перенаправления ....................................................................................................................................157
17.4. Стратегия подбора ...................................................................................................................................157
17.5. Иерархические маршруты и маршруты с пустыми путями...................................................157
17.6. Гвардия ........................................................................................................................................................159
17.7. Резольверы .................................................................................................................................................161
17.8. События в маршрутизаторе.................................................................................................................164
17.9. Параметры и данные..............................................................................................................................164
17.10. Ленивая загрузка ...................................................................................................................................166
18. Формы ..................................................................................................................................................................169
18.1. Формы, дорогие формы..........................................................................................................................169
18.2. Ориентированный на шаблоны.........................................................................................................171
18.3. Кодовое управление................................................................................................................................176
18.4. Добавление валидации .........................................................................................................................179
18.5. Ошибки и представление.....................................................................................................................181
18.6. Добавьте немного стиля .......................................................................................................................184
18.7. Создание пользовательского валидатора......................................................................................185
18.8. Группировка полей.................................................................................................................................189
18.9. Реакция на изменения...........................................................................................................................191
18.10. Обновление при размытии или только при отправке ..........................................................193
18.11. Резюме........................................................................................................................................................194
19. Зоны и магия Angular ....................................................................................................................................196
19.1. AngularJS 1.x и цикл дайджеста .........................................................................................................196
19.2. Угловые и зонные....................................................................................................................................199
20. Компиляция Angular: Вовремя и с опережением...............................................................................205
20.1. Генерация кода .........................................................................................................................................205
20.2. Сборник "Опережая время ...................................................................................................................207
21. Расширенные возможности наблюдения..............................................................................................209
21.1. Subscribe, unsubscribe и async pipe....................................................................................................209
21.2. Использование операторов .................................................................................................................214
21.3. Построение собственных наблюдаемых........................................................................................218
22. Расширенные компоненты и директивы..............................................................................................220
22.1. Просмотр запросов..................................................................................................................................220
22.2. Содержание ................................................................................................................................................223
22.3. Контентные запросы..............................................................................................................................225
22.4. Ведущий слушатель ...............................................................................................................................228
22.5. Связывание с хозяином .........................................................................................................................229
23. Интернационализация..................................................................................................................................232
23.1. Локаль ..........................................................................................................................................................232
23.2. Перевод текста ..........................................................................................................................................234
23.3. Технологические процессы и оснастка ..........................................................................................235
23.4. Трансляция сообщений в коде...........................................................................................................240
23.5. Плюрализация ..........................................................................................................................................240
23.6. Лучшие практики....................................................................................................................................242
24. Это конец.............................................................................................................................................................244
Приложение A: Changelog ...................................................................................................................................247
A.1. v1.9 - 2017-11-02............................................................................................................................................247
A.2. v1.8 - 2017-07-16............................................................................................................................................248
A.3. v1.7 - 2017-06-09............................................................................................................................................248
A.4. v1.6 - 2017-03-24............................................................................................................................................249
A.5. v1.5 - 2017-01-25............................................................................................................................................250
A.6. v1.4 - 2016-11-18............................................................................................................................................250
A.7. v1.3 - 2016-09-15............................................................................................................................................251
A.8. v1.2 - 2016-08-25............................................................................................................................................251
A.9. v1.1 - 2016-05-11............................................................................................................................................252
Глава 1. Введение
Так вы хотите стать ниндзя? Что ж, вы в надежных руках!
Но у нас с вами долгий путь, нам еще многому предстоит научиться :).
Мы живем в захватывающие времена в области веб-разработки. Появился новый Angular.
Это полная переработка старого доброго AngularJS. Почему полная переработка? Неужели
AngularJS 1.x было недостаточно?
Мне очень нравится старый добрый AngularJS. В нашей небольшой компании мы
построили несколько проектов с его использованием, внесли свой код в основной
фреймворк, обучили сотни разработчиков (да, действительно) и даже написали книгу о нем
(на французском языке, но это все равно считается).
AngularJS невероятно продуктивен, когда вы его освоили. Несмотря на все это, не мешает
нам видеть его слабые стороны. AngularJS не совершенен, в нем есть некоторые очень
сложные для понимания концепции и ловушки, которых трудно избежать.
Прежде всего, с момента создания AngularJS изменился веб. Изменился JavaScript.
Появились новые фреймворки с отличными идеями или лучшей реализацией. Мы не из тех
разработчиков, которые говорят вам, что вы должны использовать этот инструмент, а не
тот. Мы просто хорошо знаем некоторые инструменты и знаем, что подходит для
конкретного проекта. AngularJS был одним из таких инструментов, который позволял нам
создавать хорошо протестированные веб-приложения и делать их быстро. Мы также
пытались применить его там, где он не подходил. Не вините нас, это случается с лучшими
из нас.
Станет ли Angular тем инструментом, который мы, не задумываясь, будем использовать в
своих будущих проектах? Сейчас сложно сказать, потому что фреймворк очень молод, а
экосистема только расцветает.
Однако у Angular есть много интересных моментов и видение, которым обладают немногие
другие фреймворки. Он был разработан для Web будущего, с учетом ECMAScript 6, вебкомпонентов и мобильных устройств. Когда он был впервые анонсирован, я, как и многие,
сначала огорчился, что версия 2.0 не будет простым обновлением (извините, если вы
только что узнали о ней).
Но мне также не терпелось узнать, какое решение предложит талантливая команда Google.
Поэтому я начал писать эту книгу практически после первых коммитов, читая дизайндокументы, просматривая видео с конференций, пересматривая каждый коммит с самого
начала. Когда я писал свою первую электронную книгу об AngularJS 1.x, это был уже
стабильный и известный зверь. Эта книга совсем другая, она началась, когда Angular еще не
был понятен даже дизайнерам. Потому что я знал, что узнаю много нового не только об
Angular, но и о концепциях, которые определят будущее веб-разработки, причем некоторые
из них не имеют никакого отношения к Angular. И я узнал. Мне пришлось немало
покопаться в некоторых из этих концепций, и я надеюсь, что вы получите такое же
удовольствие от знакомства с ними и их отношением к Angular, как и я.
Цель этой электронной книги - развиваться вместе с Angular. Если окажется, что Angular 1
отличный фреймворк, на который мы надеемся, вы будете получать обновления с лучшими
практиками и некоторыми новыми возможностями по мере их появления (и с меньшим
количеством опечаток, потому что, несмотря на наши бесчисленные рецензии, они
наверняка остались...). И я буду рад получить от вас обратную связь - если некоторые главы
недостаточно понятны, если вы заметили ошибку или если у вас есть лучший способ для
некоторых частей.
Однако я достаточно уверен в примерах кода, поскольку все они находятся в реальном проекте, с
несколькими
2
сотни юнит-тестов. Это был единственный способ написать электронную книгу с
новорожденным фреймворком и иметь возможность отлавливать все проблемы, которые
неизбежно возникали с каждым релизом.
Даже если в конечном итоге Angular вас не убедит, я уверен, что в процессе чтения вы
почерпнете для себя кое-что новое.
Если вы приобрели пакет "Pro" (спасибо!), то по ходу книги вы будете создавать небольшое
приложение по частям. Это приложение называется PonyRacer и представляет собой сайт,
на котором можно делать ставки на скачки пони. Вы даже можете протестировать
приложение здесь! Продолжайте, я буду ждать вас.
Весело, не правда ли?
Но это не просто интересное приложение, а полноценное. Вам придется писать
компоненты, формы, тесты, использовать маршрутизатор, вызывать HTTP API (который мы
уже создали) и даже делать Web Sockets. В нем есть все, что нужно для написания
настоящего приложения. Каждое упражнение содержит скелет, набор инструкций и
несколько тестов. Как только все тесты будут успешно выполнены, упражнение будет
выполнено!
Первые 6 упражнений из пакета Pro Pack бесплатны. Остальные доступны только при
покупке нашего онлайн-тренинга. В конце каждой главы мы даем ссылки на упражнения
из Pro Pack, связанные с функциями, о которых говорилось в этой главе, помечая
бесплатные упражнения следующим знаком:
, а остальные пометим следующим
образом:
.
Если вы не купили "Pro-пакет" (а надо бы), не волнуйтесь: вы научитесь всему, что нужно.
Но вы не создадите это потрясающее приложение с красивыми пони в пиксель-арте. Это
ваша потеря :)!
Вы быстро увидите, что, помимо самого Angular, мы постарались объяснить основные
концепции, используемые фреймворком. В первых главах речь даже не идет об Angular: это
так называемые "концептуальные главы", призванные помочь вам освоить все новое и
интересное, что происходит в нашей области.
Затем мы будем постепенно наращивать наши знания о фреймворке, с компонентами,
шаблонами, трубами, формами, http, маршрутизацией, тестами...
И, наконец, мы познакомимся с продвинутыми темами. Но это уже другая история.
Хватит вступлений, давайте начнем с одной из тех вещей, которые, безусловно, изменят
наш подход к написанию кода: ECMAScript 6.
ПРИМЕЧАНИЕ В электронной книге для примеров используется Angular версии 5.0.0.
3
Angular и версионирование
Раньше эта книга называлась "Стань ниндзя с Angular 2". Потому что
изначально Google назвала свой фреймворк Angular 2. Но в октябре 2016 года
они пересмотрели свою политику в отношении версий и релизов.
ПРИМЕЧАНИЕ
Согласно плану, каждые полгода у нас будет выходить крупный релиз. А
сейчас фреймворк должен называться просто "Angular".
Не волнуйтесь, эти релизы не являются полной переработкой с отсутствием
обратной совместимости, как это было с Angular 2 по отношению к AngularJS
1.x.
Поскольку эта электронная книга будет обновляться (бесплатно) с учетом
всех следующих крупных релизов, она теперь называется "Стань ниндзя с
Angular" (без номера).
4
Глава 2. Мягкое введение в ECMASCRIPT 6
Если вы читаете эту статью, мы можем быть уверены, что вы слышали о JavaScript. То, что
мы называем JS, является одной из реализаций стандартной спецификации, называемой
ECMAScript. Н а и б о л е е и з в е с т н а я вам версия спецификации - это версия 5, которая
используется в последние годы.
Но недавно появилась новая версия спецификации, получившая название ECMASCRIPT 6,
ES6, или ECMASCRIPT 2015. В дальнейшем я буду в основном говорить ES6, поскольку это
наиболее популярный способ ссылки на нее. Он добавляет в JavaScript множество вещей,
таких как классы, константы, стрелочные функции, генераторы... В нем так много всего, что
мы не сможем рассказать обо всем этом, так как это займет целую книгу. Но Angular был
разработан так, чтобы использовать преимущества совершенно новой версии JavaScript. И
даже если вы все еще можете использовать старый JavaScript, все будет гораздо лучше, если
вы будете использовать ES6. Поэтому в этой главе мы уделим некоторое время тому, чтобы
понять, что такое ES6 и чем он будет полезен нам при создании приложений на Angular.
Это означает, что мы многое оставим в стороне и не будем исчерпывающе рассказывать об
остальном, но это будет отличной отправной точкой. Если вы уже знакомы с ES6, то можете
пропустить эти страницы. Если же нет, то вы узнаете несколько удивительных вещей,
которые пригодятся вам, даже если в будущем вы не будете использовать Angular!
2.1. Транспойлеры
ES6 только что достиг своего окончательного состояния, поэтому он еще не полностью
поддерживается всеми браузерами. И, конечно, некоторые браузеры всегда будут
опаздывать (даже если в кои-то веки Microsoft хорошо поработала с Edge). Вы можете
подумать: зачем все это нужно, если я должен внимательно следить за тем, что я могу
использовать? И вы будете правы, поскольку не так уж много приложений могут позволить
себе игнорировать старые браузеры. Но поскольку практически каждый JS-разработчик,
попробовавший ES6, хочет писать ES6-приложения, сообщество нашло решение:
транспилятор.
Транспайлер берет исходный код ES6 и генерирует код ES5, который может работать в
любом браузере. Он даже генерирует файлы карты исходного кода, что позволяет
отлаживать непосредственно исходный код ES6 из браузера. На момент написания статьи
существует две основные альтернативы для транспиляции ES6-кода:
• Traceur, проект компании Google
• Babeljs, проект, начатый молодым разработчиком Себастьяном МакКензи (в то время
ему было 17 лет, да, мне это тоже обидно), с большим количеством разнообразных
вкладов.
Каждый из них имеет свои плюсы и минусы. Например, Babeljs дает более читаемый
исходный код, чем Traceur. Но Traceur - это проект Google, поэтому, конечно, Angular и
Traceur хорошо сочетаются. Исходный код самого Angular поначалу транслировался с
помощью Traceur, а затем перешел на TypeScript. TypeScript - это язык с открытым
исходным кодом, разработанный компанией Microsoft. Он представляет собой
типизированный супернабор JavaScript, который компилируется в обычный JavaScript, но
5
об этом мы расскажем чуть позже.
Скажем прямо, Babel имеет гораздо больше возможностей, чем Traceur, поэтому я бы
посоветовал вам использовать его. Он быстро становится стандартом де-факто в этой
области.
6
Поэтому, если вы хотите поиграть с ES6 или установить его в один из своих проектов,
обратите внимание на эти транспиляторы и добавьте шаг сборки в свой процесс. Он
возьмет ваши исходные файлы ES6 и сгенерирует эквивалентный код ES5. Это работает
очень хорошо, но, конечно, некоторые из новых возможностей довольно сложно или
невозможно преобразовать в ES5, поскольку их просто не существовало. Тем не менее,
текущее состояние в значительной степени достаточно хорошее, чтобы мы могли
использовать его без опасений, так что давайте посмотрим на все эти новые блестящие
вещи, которые мы можем делать в JavaScript!
2.2. пусть
Если вы уже некоторое время пишете на JS, то знаете, что объявление переменной var - дело
непростое. Практически в любом другом языке переменная объявляется там, где
происходит объявление. Но в JS существует концепция, называемая "hoisting", которая
фактически объявляет переменную в верхней части функции, даже если вы объявили ее
позже.
Поэтому объявление переменной типа name в блоке if:
function getPonyFullName(pony) {
if (pony.isChampion) {
var name = 'Champion ' + pony.name;
возвращаемое имя;
}
return pony.name;
}
эквивалентно объявлению его в верхней части функции:
function getPonyFullName(pony) {
var name;
if (pony.isChampion) {
name = 'Champion ' + pony.name;
возвращаемое имя;
}
// имя по-прежнему доступно здесь
return pony.name;
}
В ES6 появилось новое ключевое слово для объявления переменных - let, которое ведет
себя гораздо лучше, чем можно было бы ожидать:
7
function getPonyFullName(pony) {
if (pony.isChampion) {
let name = 'Champion ' + pony.name;
возвращаемое имя;
}
// имя здесь недоступно
return pony.name;
}
8
Имя переменной теперь ограничено ее блоком. let была введена для замены var в
долгосрочной перспективе, поэтому вы можете практически отказаться от старого доброго
ключевого слова var и начать использовать let вместо него. Самое интересное, что
использование let должно быть безболезненным, а если вы не можете этого сделать, то,
скорее всего, вы заметили что-то неладное в своем коде!
2.3. Константы
Раз уж мы затронули тему новых ключевых слов и переменных, то есть еще одно, которое
может представлять интерес. В ES6 появилась const для объявления... констант! Когда вы
объявляете переменную с помощью const, она должна быть инициализирована, и вы не
можете присвоить ей другое значение позже.
const poniesInRace = 6;
poniesInRace = 7; // SyntaxError
Как и переменные, объявленные с помощью let, константы не поднимаются и объявляются
только на уровне блока.
Одна небольшая вещь может вас удивить: вы можете инициализировать константу
объектом и впоследствии изменить содержимое объекта.
const PONY = {};
PONY.color = 'blue'; // работает
Но присвоить другой объект нельзя:
const PONY = {};
PONY = {color: 'blue'}; // SyntaxError
То же самое с массивами:
const PONIES = [];
PONIES.push({ color: 'blue' }); // работает
PONIES = []; // SyntaxError
2.4. Создание объектов
Это не новое ключевое слово, но оно также может привлечь внимание при чтении ES6-кода. Теперь
9
существует
10
ярлык для создания объектов, когда создаваемое свойство объекта имеет то же имя, что и
переменная, используемая в качестве значения.
Пример:
function createPony() {
const name = 'Rainbow Dash';
const color = 'blue';
return { name: name, color: color };
}
можно упростить до
function createPony() {
const name = 'Rainbow Dash';
const color = 'blue';
return { name, color };
}
2.5. Назначение деструктуризации
Эта новая возможность может привлечь внимание и при чтении кода ES6. Теперь для
присваивания переменных из объектов или массивов существует ярлык.
В ES5:
var httpOptions = { timeout: 2000, isCache: true };
// далее
var httpTimeout = httpOptions.timeout;
var httpCache = httpOptions.isCache;
Теперь, в ES6, это можно сделать:
const httpOptions = { timeout: 2000, isCache: true };
// далее
const { timeout: httpTimeout, isCache: httpCache } = httpOptions;
И вы получите тот же результат. Это может быть немного неудобно, поскольку ключ - это
свойство, которое нужно искать в объекте, а значение - это переменная, которой нужно
присвоить. Но все работает отлично! Даже лучше: если переменная, которой вы хотите
присвоить значение, имеет то же имя, что и свойство, вы можете просто написать:
11
const httpOptions = { timeout: 2000, isCache: true };
// далее
const { timeout, isCache } = httpOptions;
// теперь у вас есть переменная с именем 'timeout'
// и один с именем 'isCache' с корректными значениями
Замечательно то, что он работает и с вложенными объектами:
const httpOptions = { timeout: 2000, cache: { age: 2 } };
// далее
const { cache: { age } } = httpOptions;
// теперь у вас есть переменная с именем 'age' и значением 2
То же самое возможно и с массивами:
const timeouts = [1000, 2000, 3000];
// далее
const [shortTimeout, mediumTimeout] = timeouts;
// теперь у вас есть переменная с именем 'shortTimeout' и значением 1000
// и переменную с именем 'mediumTimeout' со значением 2000
Разумеется, это работает и для массивов в массивах, массивов в объектах и т.д.
Одним из интересных вариантов использования этой функции может быть использование
нескольких возвращаемых значений. Представьте себе функцию randomPonyInRace
которая возвращает пони и его позицию в гонке.
function randomPonyInRace() {
const pony = { имя: 'Rainbow Dash' };
const position = 2;
// ...
return { pony, position };
}
const { position, pony } = randomPonyInRace();
Новая возможность деструктуризации заключается в том, что возвращаемая методом
позиция присваивается переменной position, а пони - переменной pony! А если вам не
важна позиция, вы можете написать:
12
function randomPonyInRace() {
const pony = { имя: 'Rainbow Dash' };
const position = 2;
// ...
return { pony, position };
}
const { pony } = randomPonyInRace();
А у вас будет только пони!
2.6. Параметры и значения по умолчанию
Одной из особенностей JavaScript является то, что он позволяет разработчикам вызывать
функцию с любым количеством аргументов:
• Если вы передаете больше аргументов, чем количество параметров, то лишние
аргументы игнорируются (точнее, их все равно можно использовать с помощью
переменной special arguments).
• если передать меньше аргументов, чем количество параметров, то недостающий
параметр будет установлен в значение undefined.
Последний случай является наиболее актуальным для нас. Обычно мы передаем меньше
аргументов, когда параметры являются необязательными, как в следующем примере:
function getPonies(size, page) {
size = size || 10;
page = page || 1;
// ...
server.get(size, page);
}
Необязательные параметры обычно имеют значение по умолчанию. Оператор OR
вернет правый операнд, если левый не определен, что будет иметь место, если
параметр не был предоставлен (точнее, если он фальшивый, т.е. 0, false, "" и т.д.).
Используя этот прием, можно вызвать функцию getPonies:
getPonies(20, 2);
getPonies(); // то же, что и getPonies(10, 1);
getPonies(15); // то же, что и getPonies(15, 1);
Это работало нормально, но без чтения тела функции было не совсем очевидно, что
параметры являются необязательными и имеют значения по умолчанию. В ES6 появился
более точный способ указания параметров по умолчанию - непосредственно в определении
функции:
13
function getPonies(size = 10, page = 1) {
// ...
server.get(size, page);
}
Теперь совершенно ясно, что параметр size будет равен 10, а параметр page будет равен 1, если он не
указан.
ПРИМЕЧАНИЕ
Правда, есть небольшое отличие: теперь 0 или "" являются допустимыми
значениями и не будут заменены на значение по умолчанию, как это
было бы в случае size = size || 10. Теперь это будет выглядеть так: size =
size === undefined ? 10: size;.
Значение по умолчанию также может быть вызовом функции:
function getPonies(size = defaultSize(), page = 1) {
// метод defaultSize будет вызван, если размер не указан
// ...
server.get(size, page);
}
или даже другие переменные, либо глобальные переменные, либо другие параметры функции:
function getPonies(size = defaultSize(), page = size - 1) {
// если страница не указана, то она будет
установлена в значение
// параметра size минус один.
// ...
server.get(size, page);
}
Заметим, что если попытаться обратиться к параметрам справа, то их значение всегда будет
неопределенным:
function getPonies(size = page, page = 1) {
// размер всегда будет неопределенным, так как параметр page
находится справа от него. server.get(size, page);
}
Этот механизм для параметров может быть применен и к значениям, например, при использовании
деструктурирующего присваивания:
const { timeout = 1000 } = httpOptions;
// теперь у вас есть переменная с именем 'timeout',
// со значением параметра 'httpOptions.timeout', если он существует
// или 1000, если нет
14
2.7. Оператор на отдыхе
В ES6 появился новый синтаксис для определения переменных параметров в функциях. Как
уже говорилось в предыдущей части, в функцию всегда можно было передать
дополнительные аргументы и получить их с помощью переменной special arguments.
Поэтому можно было сделать примерно так:
function addPonies(ponies) {
for (var i = 0; i < arguments.length; i++) {
poniesInRace.push(arguments[i]);
}
}
addPonies('Rainbow Dash', 'Pinkie Pie');
Но, думаю, можно согласиться, что это некрасиво и неочевидно: поскольку параметр ponies
никогда не используется, откуда нам знать, что можно передать несколько пони?
ES6 предоставляет нам гораздо лучший синтаксис, используя оператор rest ...:
function addPonies(...ponies) {
for (let pony of ponies) {
poniesInRace.push(pony);
}
}
ponies теперь является настоящим массивом, над которым мы можем выполнять
итерации. Цикл for ... of, используемый для итерации, также является новой
особенностью ES6. Он позволяет выполнять итерацию именно по значениям коллекции, а
не по ее свойствам, как это было бы в for ... in. Не кажется ли вам, что теперь наш код стал
красивее и нагляднее?
Оператор rest может работать и при деструктуризации данных:
const [winner, ...losers] = poniesInRace;
// предполагается, что 'poniesInRace' - это массив, содержащий несколько
пони
// "Победитель" получит первую пони,
// а "проигравшие" будут представлять собой массив из других
Оператор rest не следует путать с оператором spread, который, надо отдать должное,
выглядит очень похоже! Но оператор spread является противоположным: он берет массив и
раскладывает его по переменным аргументам. Единственные примеры, которые я имею в
виду, - это функции типа min или max, которые получают переменные аргументы и
которые можно вызвать на массиве:
const ponyPrices = [12, 3, 4];
const minPrice = Math.min(...ponyPrices);
15
2.8. Классы
Одна из самых знаковых новых возможностей, которую мы будем активно использовать
при написании приложений на Angular: ES6 вводит классы в JavaScript! Теперь вы можете
легко использовать классы и наследование в JavaScript. Вы всегда могли это делать,
используя прототипическое наследование, но это было непростой задачей, особенно для
новичков.
Теперь это очень просто, посмотрите:
класс Pony {
constructor(color) {
this.color = color;
}
toString() {
return `${this.color} pony`;
// видите это? Это еще одна замечательная особенность ES6,
называемая шаблонными литералами
// мы быстро поговорим о них!
}
}
const bluePony = new Pony('blue');
console.log(bluePony.toString()); // синий пони
Объявления классов, в отличие от объявлений функций, не являются подъемными,
поэтому перед использованием класса необходимо его объявить. Возможно, вы
заметили специальную функцию constructor. Именно эта функция вызывается, когда мы
создаем новую пони с помощью оператора new. Здесь ей нужен цвет, и мы создаем
новый экземпляр Pony с цветом "синий". Класс также может иметь методы,
вызываемые на экземпляре, как, например, метод toString() здесь.
Он также может иметь статические атрибуты и методы:
класс Pony {
static defaultSpeed() {
возврат 10;
}
}
Статические методы могут быть вызваны только непосредственно на классе:
const speed = Pony.defaultSpeed();
Класс может иметь геттеры и сеттеры, если вы хотите подключить эти операции:
16
класс Pony {
get color() {
console.log('get color');
return this._color;
}
set color(newColor) {
console.log(`set color ${newColor}`);
this._color = newColor;
}
}
const pony = new Pony();
pony.color = 'red';
// "установить красный
цвет" console.log(pony.color);
// 'get color'
// 'red'
И, конечно, если у вас есть классы, то в ES6 вы также имеете наследование из коробки.
class Animal {
speed() {
возврат 10;
}
}
class Pony extends Animal {
}
const pony = new Pony();
console.log(pony.speed()); // 10, так как Pony наследует родительский метод
Животное называется базовым классом, а Пони - производным классом. Как видно,
производный класс имеет методы базового класса. Он также может переопределять их:
class Animal {
speed() {
возврат 10;
}
}
class Pony extends Animal {
speed() {
return super.speed() + 10;
}
}
const pony = new Pony();
console.log(pony.speed()); // 20, так как Pony переопределяет родительский метод
17
Как видно, ключевое слово super позволяет вызвать метод базового класса, при этом super.speed()
например.
Ключевое слово super может также использоваться в конструкторах для вызова конструктора
базового класса:
класс Animal {
constructor(speed) {
this.speed = speed;
}
}
class Pony extends Animal {
constructor(speed, color) {
super(speed);
this.color = color;
}
}
const pony = new Pony(20, 'blue');
console.log(pony.speed); // 20
2.9. Обещания
Обещания не так уж и новы, и вы, возможно, уже знаете или используете их, поскольку они
были большой частью AngularJS 1.x. Но поскольку вы будете часто использовать их в
Angular, и даже если вы просто используете JS, я думаю, что важно сделать остановку.
Promises призваны упростить асинхронное программирование. Наш JS-код полон
асинхронных вещей, таких как AJAX-запросы, и обычно мы используем обратные вызовы
для обработки результатов и ошибок. Но это может привести к запутыванию кода, когда
обратные вызовы находятся внутри обратных вызовов, и код становится трудно читать и
поддерживать. Promises гораздо лучше, чем обратные вызовы, поскольку они сглаживают
код, а значит, делают его более понятным. Рассмотрим простой пример, в котором нам
нужно получить пользователя, затем его права, а затем обновить меню, когда они у нас
есть.
С обратными вызовами:
getUser(login, function (user) {
getRights(user, function (rights) {
updateMenu(rights);
});
});
Теперь сравним это с обещаниями:
18
getUser(login)
.then(function (user) {
return getRights(user);
})
.then(function (rights) {
updateMenu(rights);
})
Мне нравится эта версия, потому что она выполняется по мере чтения: Я хочу получить
пользователя, затем получить его права, затем обновить меню.
Как видите, обещание является объектом типа 'thenable', что означает, что у него есть метод
then. Этот метод принимает два аргумента: один обратный вызов успеха и один обратный
вызов отказа. Обещание имеет три состояния:
• pending: пока обещание не выполнено, например, наш вызов сервера еще не завершен.
• Выполнено: когда обещание завершается успехом, например, вызов сервера возвращает
HTTP-статус OK.
• rejected: когда обещание не выполнено, например, сервер возвращает статус 404.
Если обещание выполнено, то вызывается обратный вызов success с результатом в качестве
аргумента. Если обещание отклонено, то вызывается обратный вызов reject, аргументом
которого является отклонённое значение или ошибка.
Итак, как же создать обещание? Довольно просто: есть новый класс Promise,
конструктор которого ожидает функцию с двумя параметрами - resolve и reject.
const getUser = function (login) {
return new Promise(function (resolve, reject) {
// асинхронные действия, например, получение пользователей с
сервера, возврат ответа
if (response.status === 200) {
resolve(response.data);
} else {
reject('Нет пользователя');
}
});
};
После создания обещания можно зарегистрировать обратные вызовы, используя метод then.
Этот метод может принимать два параметра - два обратных вызова, которые вы хотите
вызвать в случае успеха или в случае неудачи. Здесь мы передаем только обратный вызов в
случае успеха, игнорируя возможную ошибку:
getUser(login)
.then(function (user) {
console.log(user);
})
19
Как только обещание будет разрешено, будет вызван обратный вызов success (здесь просто
запись пользователя в консоль).
Самое замечательное, что при этом код становится более плоским. Например, если ваш
обратный вызов resolve также возвращает обещание, вы можете написать:
getUser(login)
.then(function (user) {
return getRights(user) // getRights возвращает обещание
.then(function (rights) {
return updateMenu(rights);
});
})
но более красиво:
getUser(login)
.then(function (user) {
return getRights(user); // getRights возвращает обещание
})
.then(function (rights) {
return updateMenu(rights);
})
Еще одним интересным моментом является обработка ошибок, поскольку можно
использовать один обработчик для каждого обещания или один для всей цепочки.
По одному на каждое обещание:
getUser(login)
.then(function (user) {
return getRights(user);
}, function (error) {
console.log(error); // будет вызван в случае неудачи getUser
return Promise.reject(error);
})
.then(function (rights) {
return updateMenu(rights);
}, function (error) {
console.log(error); // будет вызван в случае неудачи getRights
return Promise.reject(error);
})
Один на цепь:
20
getUser(login)
.then(function (user) {
return getRights(user);
})
.then(function (rights) {
return updateMenu(rights);
})
.catch(function (error) {
console.log(error); // будет вызван в случае неудачи getUser или
getRights
})
Вы должны серьезно изучить Promises, потому что они станут новым способом написания
API, и каждая библиотека будет их использовать. Даже стандартные: например, новый Fetch
API.
2.10. Функции стрелок
Одна вещь, которая мне очень нравится в ES6, - это новый синтаксис стрелочных функций,
использующий оператор "жирной стрелки" (⇒). Это очень удобно для обратных вызовов и
анонимных функций!
Возьмем наш предыдущий пример с обещаниями:
getUser(login)
.then(function (user) {
return getRights(user); // getRights возвращает обещание
})
.then(function (rights) {
return updateMenu(rights);
})
можно записать с помощью стрелочных функций, например, так:
getUser(login)
.then(user => getRights(user))
.then(rights => updateMenu(rights))
Насколько это круто? НАСТОЛЬКО круто!
Заметим, что возврат также неявен, если нет блока: не нужно писать user ⇒ return
getRights(user). Но если бы у нас был блок, то потребовался бы явный возврат:
21
getUser(login)
.then(user => {
console.log(user);
return getRights(user);
})
.then(rights => updateMenu(rights))
И у нее есть особый трюк, дающий большую власть над обычными функциями: this остается
лексически ограниченным, то есть у этих функций нет нового this, как у других функций.
Рассмотрим пример, когда с помощью функции map выполняется итерация по массиву для
нахождения максимального значения.
В ES5:
var maxFinder = {
max: 0,
find: function (numbers) {
// выполним
итерацию
numbers.forEach(
function (element) {
// если элемент больше, установить его как максимальный
if (element > this.max) {
this.max = element;
}
});
}
};
maxFinder.find([2, 3, 4]);
// занести результат в
журнал
console.log(maxFinder.max);
Можно было бы ожидать, что это будет работать, но этого не происходит. Если у вас
хороший глаз, то вы могли заметить, что forEach в функции find использует this, но this не
привязан к объекту. Таким образом, this.max не является max объекта maxFinder... Конечно,
это можно легко исправить, используя псевдоним:
22
var maxFinder =
{ max: 0,
find: function (numbers) {
var self = this;
numbers.forEach(
function (element) {
if (element > self.max) {
self.max = element;
}
});
}
};
maxFinder.find([2, 3, 4]);
// занести результат в
журнал
console.log(maxFinder.max);
или связать это:
var maxFinder = {
max: 0,
find: function (numbers) {
numbers.forEach(
function (element) {
if (element > this.max) {
this.max = element;
}
}.bind(this));
}
};
maxFinder.find([2, 3, 4]);
// занести результат в
журнал
console.log(maxFinder.max);
или даже передавать его в качестве второго параметра функции forEach (для чего она и была
разработана):
23
var maxFinder =
{ max: 0,
find: function (numbers) {
numbers.forEach(
function (element) {
if (element > this.max) {
this.max = element;
}
}, this);
}
};
maxFinder.find([2, 3, 4]);
// занести результат в
журнал
console.log(maxFinder.max);
Но теперь есть еще более элегантное решение с помощью синтаксиса стрелочных функций:
const maxFinder = { max:
0,
find: function (numbers) {
numbers.forEach(element = > {
if (element > this.max) {
this.max = element;
}
});
}
};
maxFinder.find([2, 3, 4]);
// занести результат в
журнал
console.log(maxFinder.max);
Это делает стрелочные функции идеальными кандидатами на анонимные функции в обратных
вызовах!
2.11. Наборы и карты
Это коротко: теперь в ES6 у вас есть правильные коллекции. Ура \o/! Раньше роль карты
в ы п о л н я л и словари, но теперь мы можем использовать класс Map:
const cedric = { id: 1, name: 'Cedric' };
const users = new Map();
users.set(cedric.id, cedric); // добавляет
пользователя
console.log(users.has(cedric.id)); // true
console.log(users.size); // 1
users.delete(cedric.id); // удаляет
24пользователя
Download