Итоговый проект
Представьте кладовщика с тетрадью. На каждой строке в ней записаны название товара и число единиц на полках. Привезли товар — кладовщик прибавляет число в строке. Пришли забрать — он сначала проверяет, хватает ли единиц, и только потом вычитает. Если не хватает, он отказывает, и запись в тетради остаётся прежней.
Класс в настоящей программе обычно опирается сразу на несколько идей. Он хранит данные в коллекции, меняет их методами и бросает ошибку, когда операцию выполнить нельзя. Итоговая задача устроена так же: новых конструкций в ней нет, нужно соединить знакомые.
Склад
Задача — склад, который считает единицы каждого товара. Класс Inventory играет роль тетради кладовщика: он хранит количества. Его методы делают четыре дела:
addкладёт товар на склад;takeзабирает товар со склада;countназывает количество товара;namesвозвращает список товаров.
Экземпляр склада создаёт функция createInventory, и она уже написана в заготовке. Фабрикой в теме о замыканиях называли функцию, которая создаёт замыкания. Фабрика может создавать и объекты, и createInventory устроена именно так. Класс тестам не виден, а функцию, объявленную словом function, они видят, поэтому вызывают фабрику, а не new Inventory().
| Часть задачи | Что понадобится |
|---|---|
| хранилище | поле класса с new Map() |
add и count | get и set у Map, ?? |
take | сравнение, throw new RangeError(…) |
names | for…of, push, sort |
Храните количества в Map, а не в обычном объекте {}. У объекта есть свойства, унаследованные от прототипа: {}["constructor"] — это функция, а не undefined. У нового Map таких ключей нет, и get для любого незнакомого названия вернёт undefined.
Здесь аналогия с тетрадью заканчивается. Строки в тетради идут в порядке записи, а names должен вернуть названия по алфавиту: сортировку делает ваш код.
Метод take
Если единиц не хватает, take бросает RangeError и количество не меняет. Поэтому в методе сначала проверьте, хватает ли единиц, и только потом меняйте количество. Так же поступает кладовщик: он не вычёркивает товар, пока не убедился, что тот есть.
Тесты вызывают take внутри try…catch и проверяют, что пойманная ошибка — RangeError. Товар, у которого не осталось единиц, в список names не попадает.
Порядок работы
Работайте по шагам:
- Начните с хранилища: без него остальным методам не с чем работать.
- Напишите один метод.
- Запустите тесты и переходите к следующему методу.
Каждый тест создаёт свой склад через createInventory(), поэтому ошибка в одном тесте не мешает другому.
Как читать вывод тестов
Пройденный тест печатает строку PASS со своим именем. Непройденный печатает FAIL с именем, а под ним — что случилось. Так заготовка отвечает на первый тест:
FAIL test_add_and_count
add("apple", 5), add("apple", 3): count("apple") = -1, want 8Давайте разберём вторую строку:
- перед двоеточием стоят вызовы, которые тест сделал заранее;
- после двоеточия стоит проверяемый вызов;
- справа от
=стоит то, что вернул ваш код; - после
wantстоит ожидаемое значение.
Здесь -1 пришло из заготовки: метод count ещё не написан. Последняя строка вывода показывает, сколько тестов прошло и сколько нет; у заготовки это 0 passed, 8 failed.
После курса
Эта задача завершает курс. Большие программы делят на файлы через ES-модули с import и export; в этот курс они не входят. Дальше проверьте себя на симуляторе собеседования по JavaScript на этом сайте. Он задаёт вопросы по тем же темам — от типов и замыканий до классов, ошибок и промисов — и оценивает ответы.
Главное
- Итоговая задача соединяет знакомые конструкции: класс,
Map,throwиtry…catch. - Тесты создают склад через готовую фабрику
createInventory, а не черезnew Inventory(). - В
takeсначала идёт проверка, потом изменение: при нехватке количество не меняется. - Строка под
FAILпоказывает вызовы теста, полученное значение и ожидаемое послеwant.
Подпишись, чтобы пройти курс
Курс бесплатный. Войди через Telegram и подпишись на канал — откроются все уроки.