я лично тупо пилил мелкие проекты — тудушку, калькулятор, даже модалку свою. Ещё задачки на CodeWars/LeetCode хорошо вбивают базу, особенно когда начинаешь понимать где и что применять. Главное не залипать только в теорию, код сам всё в голове расставит по полочкам.
Попробуйте не просто решать задачи, а переписывать встроенные методы языка: напишите свою реализацию map, filter, reduce, bind или debounce. Это заставит разобраться с замыканиями, контекстом и колбэками, а не просто использовать готовое. Начните с простого, затем усложняйте — например, добавьте обработку граничных случаев.
Ещё один приём — намеренно ломать рабочий код и чинить его. Возьмите небольшой скрипт, измените порядок объявлений, уберите return, замените стрелочную функцию на обычную и посмотрите, что изменится и почему. Это быстро выявляет пробелы в понимании.
Полезно вести конспект паттернов и раз в несколько дней воспроизводить их по памяти, не подглядывая. Например, написать функцию, которая принимает массив чисел и возвращает новый, где только чётные, умноженные на два. Если получается сходу — база закрепляется.