Перейти к содержимому
Теория · Итоговый проект · урок 6 из 7

Итоговый проект

Представьте кладовщика с тетрадью. На каждой строке в ней записаны название товара и число единиц на полках. Привезли товар — кладовщик прибавляет число в строке. Пришли забрать — он сначала проверяет, хватает ли единиц, и только потом вычитает. Если не хватает, он отказывает, и запись в тетради остаётся прежней.

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

Склад

Задача — склад, который считает единицы каждого товара. Класс Inventory играет роль тетради кладовщика: он хранит количества. Его методы делают четыре дела:

  • add кладёт товар на склад;
  • take забирает товар со склада;
  • count называет количество товара;
  • names возвращает список товаров.

Экземпляр склада создаёт функция createInventory, и она уже написана в заготовке. Фабрикой в теме о замыканиях называли функцию, которая создаёт замыкания. Фабрика может создавать и объекты, и createInventory устроена именно так. Класс тестам не виден, а функцию, объявленную словом function, они видят, поэтому вызывают фабрику, а не new Inventory().

Часть задачиЧто понадобится
хранилищеполе класса с new Map()
add и countget и set у Map, ??
takeсравнение, throw new RangeError(…)
namesfor…of, push, sort

Храните количества в Map, а не в обычном объекте {}. У объекта есть свойства, унаследованные от прототипа: {}["constructor"] — это функция, а не undefined. У нового Map таких ключей нет, и get для любого незнакомого названия вернёт undefined.

Здесь аналогия с тетрадью заканчивается. Строки в тетради идут в порядке записи, а names должен вернуть названия по алфавиту: сортировку делает ваш код.

Метод take

Если единиц не хватает, take бросает RangeError и количество не меняет. Поэтому в методе сначала проверьте, хватает ли единиц, и только потом меняйте количество. Так же поступает кладовщик: он не вычёркивает товар, пока не убедился, что тот есть.

Тесты вызывают take внутри try…catch и проверяют, что пойманная ошибка — RangeError. Товар, у которого не осталось единиц, в список names не попадает.

Порядок работы

Работайте по шагам:

  1. Начните с хранилища: без него остальным методам не с чем работать.
  2. Напишите один метод.
  3. Запустите тесты и переходите к следующему методу.

Каждый тест создаёт свой склад через createInventory(), поэтому ошибка в одном тесте не мешает другому.

Как читать вывод тестов

Пройденный тест печатает строку PASS со своим именем. Непройденный печатает FAIL с именем, а под ним — что случилось. Так заготовка отвечает на первый тест:

TEXT
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 и подпишись на канал — откроются все уроки.

Войти другим способом