Первая часть: знакомство с отладчиком
Вторая часть: узнаём значение переменной без console.log


Стек вызовов

Продолжаем отладку приложения со списком дел. В этот раз будем чинить удаление задач. Откройте приложение в новой вкладке. Эта версия тоже сломана нарочно, чтобы мы разобрались, что такое стек вызовов.

Как откроете приложение, добавьте несколько своих задач в список дел. Затем удалите первую в списке задачу. Кнопка Delete. Пока всё работает. Теперь удалите последнюю в списке задачу. Опачки! Почему-то удалилась первая. Если не заметили, попробуйте снова: удалите любую задачу, кроме первой. То же самое! Какую бы задачу мы не удаляли, пропадает первая в списке.

Вы знаете, что делать: открываем инструменты разработчика, затем отладчик. Нас интересует функция removeSingle, файл app.js, 39-я строка. Именно эта функция отвечает за удаление задач из списка.

Поставим точку останова на 40-й строке. Попробуйте теперь удалить любую задачу из списка, кроме первой. Сработает точка останова, и мы сможем построчно выполнять код, чтобы найти ошибку.

В прошлой статье мы использовали кнопку навигации «Перешагнуть через», чтобы найти ошибку. Мы можем воспользоваться ей снова, но особенность этой кнопки в том, что код выполняется построчно целиком. Даже если это вызов функции. А что, если ошибка «прячется» в этой функции?

Что, если проблема не в removeSingle, а в spliceItem? В этом случае выручит кнопка «Зайти в»:

Кнопка «Зайти в» на панели навигации
Кнопка «Зайти в» на панели навигации

Кнопка «Зайти в» позволяет «провалиться» в функцию вместо её вызова целиком и отладить её код тоже.

После остановки на 40-й строке нажимайте «Зайти в» до тех пор, пока не окажетесь на 24-й строке, внутри функции createList. Если вы не поймёте, как там оказались, ничего страшного. Разберёмся!

Функция createList принимает массив list с данными для отрисовки списка задач. Давайте посмотрим на его элементы. Наведите курсор на параметр list или загляните в блок «Области видимости».

В массиве с данными вы найдёте задачу, которую удалили. Значит, в функцию createList передана неверная информация. Но в самой функции ошибки нет, она где-то раньше.

Обратимся к панели инструментов отладчика, та что справа. В блоке «Стек вызовов» можно найти список всех вызванных функций до момента остановки. Кроме названия функции, там указаны номер строки и имя файла, где функция была вызвана. Количество функций говорит о размере стека. Выделение показывает, как глубоко мы в стеке.

В нашем случае стек глубиной в четыре вызова. Точка останова в функции removeSingle. Затем мы «провалились» в spliceItem, после в saveList и вот мы в createList:

Блок «Стек вызовов» на панели инструментов, справа, развёрнут
Блок «Стек вызовов» на панели инструментов, справа, развёрнут

По стеку можно перемещаться. Для этого достаточно кликнуть по нужной функции в списке.

Чтобы найти ошибку, прогуляемся по стеку. Кликнем по функции saveList. Отладчик перенесёт нас к её объявлению. Это простая, возможно даже лишняя, функция. Она всего лишь вызывает createList и передаёт ей аргументами глобальные переменные items и todoList. Вряд ли ошибка в такой простой функции, поэтому двигаемся дальше.

Кликнем в стеке по функции spliceItem. Так-так-так... Значение параметра index не определено. Это уже зацепка!

Значение index (подчёркнуто жёлтым) можно увидеть
при наведении или в блоке «Области видимости»
Значение index (подчёркнуто жёлтым) можно увидеть при наведении или в блоке «Области видимости»

Подымемся выше, в функцию removeSingle, чтобы понять, почему в spliceItem передаётся undefined. Ошибка где-то здесь:

const index = el.dataset.number;

Наведём курсор на index, увидим undefined. Если наведём на number — то же самое. Тогда давайте посмотрим значение dataset. Вот оно! В объекте dataset нет ключа number. Индекс записан по ключу index, что логично.

Даже не ошибка, обычная опечатка. Останется только поправить код:

const index = el.dataset.index;

Но исправления уже за рамками нашей статьи... Дело раскрыто.


Совет в тему

В нашем приложении всего десяток функций. Каждая длинной в пару строк. Найти нужную несложно. Но что, если в файле сотня функций? Также искать глазами? Нет! Воспользуйтесь поиском по функциям.

Для поиска нажмите shift + control + O в Windows и Linux или shift + command + O в macOS. Далее впишите имя функции, которую хотите найти. Или воспользуйтесь стрелками на клавиатуре для навигации по списку всех функций в приложении.

Поиск по функциям файла app.js
Поиск по функциям файла app.js

Четвёртая часть: точки останова с условием

Комментарии (3)


  1. apapacy
    13.11.2021 19:16

    спасибо. интересная тема. мечтаю уйти от console.log() но не хватает силы воли.


    1. sashasushko Автор
      13.11.2021 20:26

      На переходный период есть log point, это как break point только с логированием вместо остановки.

      В четвёртой части расскажу о нём.


    1. sashasushko Автор
      13.11.2021 20:27

      К тому же, отладка с source maps - это то ещё удовольствие. Сразу же хочется в объятья console.log вернуться.