Поиск по сайту:
В хорошей системе не может быть слабого языка команд. (Алан.Дж.Перлис)

Руководство для начинающих по отладке (JavaScript)

27.09.2023
Руководство для начинающих по отладке (JavaScript)

Если вы читаете это, возможно, вы студент или с тревогой смотрите на свой код, пытаясь понять, где что-то пошло не так. Или, возможно, вы просто надеетесь открыть для себя несколько полезных приемов для отладки вашего кода в будущем. В этом посте мы рассмотрим несколько методов, которые мы использовали для отладки своего кода, а также несколько простых примеров для подражания.

 

Но сначала, что такое отладка и как это будет применимо к вам?

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

 

Несколько советов, которые облегчат отладку вашего кода

  1. Сделайте свой код максимально выразительным или простым для понимания. Это может означать маркировку переменных и функций в соответствии с тем, что они выполняют (например, используя такие имена переменных, как firstName и lastName, а не string1 и string2). Это также может означать использование встроенных методов (таких как карта массива), которые подсказывают, какое возвращаемое значение следует ожидать.
  2. Аналогичным образом, старайтесь, чтобы ваши функции выполняли одну главную цель. Это уменьшит количество ошибок и упростит понимание вашего кода.
  3. Объявляйте переменные и функции только там, где они необходимы. Если переменные и функции доступны с помощью кода, которому они не нужны (например, если они были объявлены в глобальной области видимости без необходимости), отследить ошибки будет намного сложнее.
  4. По возможности избегайте изменений. Бывают случаи, когда вам захочется изменить состояние массива или объекта, но, когда это возможно, лучше всего обновить их неразрушающим образом (например, создав копии перед изменением). В связи с этим также безопаснее объявлять свои переменные с помощью const, если только вы уже не знаете, что будете переназначать переменную по всему вашему коду. Это предотвратит непреднамеренное изменение значения переменной и вместо этого может привести к полезной ошибке, подобной этой: Uncaught TypeError: Assignment to constant variable.
  5. Часто тестируйте свой код по мере его написания. Гораздо сложнее найти ошибку, когда вы работаете со многими непроверенными функциями одновременно.

 

Хорошо, теперь, когда мы разобрались с этим, вот несколько опций отладчика. Теперь мы покажем примеры с использованием простого цикла for. Ознакомьтесь с документацией MDN, если вам нужно обновление.

 

Вывод на консоль

Вы можете проверить свои предположения по всему коду, используя инструкции console.log().

Допустим, у нас есть функция, предназначенная для получения массива учащихся и возврата нового массива, содержащего только учащихся, имена которых начинаются с ‘A’.

const allStudents = ["AndreyEx", "Max", "Alex", "Dasha", "Anna", "Dennis"];

function startsWithJ(array) {
  const aStudents = [];
  for (let i = 0; i < array.length; i++) {
    const currentStudent = array[i];
    const firstLetter = currentStudent[1];
    if (firstLetter === "A") {
      aStudents.push(currentStudent);
    }
  }
  return aStudents;
}

startsWithJ(allStudents); 
// => []

 

Когда мы запускаем нашу функцию с переданным массивом allStudents, она возвращает пустой массив. Это не то, чего мы ожидали – мы хотели, чтобы он возвращался ['AndreyEx', 'Alex', 'Anna']. Возможно, вы быстро поймете, где мы ошиблись, а возможно, и нет (и это нормально!). В любом случае, потерпите немного, пока мы добавим инструкции console.log() для отладки этой функции.

Читать  Оптимизация кода в компьютерном дизайне

Одно из наших предположений относительно этого кода заключается в том, что он корректно обращается к каждому элементу в массиве allStudents. Мы можем использовать console.log() для печати имени каждого ученика в нашем исходном массиве, вот так:

const allStudents = ["AndreyEx", "Max", "Alex", "Dasha", "Anna", "Dennis"];

function startsWithJ(array) {
  const aStudents = [];
  for (let i = 0; i < array.length; i++) {
    const currentStudent = array[i];
    console.log(currentStudent); //ДОБАВЛЕНА СТРОКА
    const firstLetter = currentStudent[1];
    if (firstLetter === "A") {
      aStudents.push(currentStudent);
    }
  }
  return aStudents;
}

startsWithJ(allStudents);
// LOG: AndreyEx
//      Max
//      Alex
//      Dasha
//      Anna
//      Dennis 
// => []

 

Имя каждого учащегося корректно выводится на консоль, поэтому мы знаем, что наш цикл for настроен правильно. Давайте проверим другое предположение – что мы правильно проверяем первую букву имени каждого учащегося. Мы можем “видеть, о чем думает машина”, когда получаем доступ к первой букве, печатая нашу переменную firstLetter.

const allStudents = ["AndreyEx", "Max", "Alex", "Dasha", "Anna", "Dennis"];

function startsWithJ(array) {
  const aStudents = [];
  for (let i = 0; i < array.length; i++) {
    const currentStudent = array[i];
    const firstLetter = currentStudent[1];
    console.log(firstLetter); //ДОБАВЛЕНА СТРОКА
    if (firstLetter === "A") {
      aStudents.push(currentStudent);
    }
  }
  return aStudents;
}

startsWithJ(allStudents);
// LOG: n
//      a
//      l
//      a
//      n
//      e 
// => []

 

Здесь мы видим, что наше предположение было неверным. Мы случайно проверяем вторую букву каждого имени, и поэтому firstLetter === 'A' это никогда не соответствует действительности. Нам нужно изменить firstLetter назначение на currentStudent[0] вместо currentStudent[1]. Вот наш окончательный результат:

const allStudents = ["AndreyEx", "Max", "Alex", "Dasha", "Anna", "Dennis"];

function startsWithJ(array) {
  const aStudents = [];
  for (let i = 0; i < array.length; i++) {
    const currentStudent = array[i];
    const firstLetter = currentStudent[0];
    if (firstLetter === "A") {
      aStudents.push(currentStudent);
    }
  }
  return aStudents;
}

startsWithJ(allStudents);
// => [ 'AndreyEx', 'Alex', 'Anna' ]

 

Хотя это довольно простой пример, использование console.log() для просмотра значений переменных, вызовов функций и т.д. Является допустимым способом отслеживания более сложного кода.

 

Отладчик узлов

Теперь мы переходим к инструментам отладки, которые позволяют нам “приостанавливать” наш код и внимательнее смотреть на то, что происходит на каждом шаге. Мы начнем с того, который предоставляется Node для терминала (убедитесь, что Node установлен!).

Сначала используйте свой терминал для перехода к каталогу, в котором хранится ваш код. Мы будем использовать ту же функцию, что и выше, но на этот раз с другой ошибкой.

const allStudents = ["AndreyEx", "Max", "Alex", "Dasha", "Anna", "Dennis"];

function startsWithJ(array) {
  const aStudents = [];
  for (let i = 0; i <= array.length; i++) {
    const currentStudent = array[i];
    const firstLetter = currentStudent[0];
    if (firstLetter === "A") {
      aStudents.push(currentStudent);
    }
  }
  return aStudents;
}

startsWithJ(allStudents);

 

Когда мы запускаем это, мы получаем следующую ошибку:

const firstLetter = currentStudent[0];
TypeError: Cannot read properties of undefined (reading '0')

 

Аналогично использованию console.log(), мы выберем место в коде, куда мы хотим заглянуть внутрь и посмотреть, что происходит. В этом случае мы будем использовать debugger ключевое слово. Поскольку мы видим, что один из параметров currentStudent не определен, давайте поместим инструкцию debugger рядом с объявленной переменной currentStudent.

function startsWithJ(array) {
  const aStudents = [];
  for (let i = 0; i <= array.length; i++) {
    const currentStudent = array[i];
    debugger; //ДОБАВЛЕНА СТРОКА
    const firstLetter = currentStudent[0];
    if (firstLetter === "A") {
      aStudents.push(currentStudent);
    }
  }
  return aStudents;
}

 

Читать  Рефакторинг кода: искусство улучшения программного обеспечения

Оттуда вы можете запустить отладчик с помощью команды node inspect index.js в вашем терминале (используйте имя вашего файла вместо index.js).

Теперь запустите cont по приглашению debug, чтобы запустить цикл. Он остановится в вашей точке останова debugger. Теперь мы видим нечто подобное в нашем терминале:

break in index.js:7
  5   for (let i = 0; i <= array.length; i++) {
  6     const currentStudent = array[i];
> 7     debugger;
  8     const firstLetter = currentStudent[0];
  9     if (firstLetter === "A") {
debug>

 

В приглашении debug давайте откроем REPL, выполнив команду repl. Оттуда мы можем проверить значения переменных, введя их имена в терминале. Мы начнем с проверки значения i и currentStudent.

debug> repl
Press Ctrl+C to leave debug repl
> i
0
> currentStudent
'AndreyEx'

 

В этом есть смысл! Мы находимся на нашей первой итерации цикла for, где i должно быть 0 и currentStudent должно быть ‘AndreyEx’ (первый ученик в нашем массиве allStudents). Пока все идет хорошо. Чтобы продолжить пошаговое выполнение кода к нашей следующей итерации, нажмите Ctrl + C для выхода из REPL и снова введите cont в приглашении debug.

Теперь, когда мы снова входим в REPL, мы должны быть на второй итерации нашего цикла for. Мы можем подтвердить это, снова проверив значения i и currentStudent.

debug> repl
Press Ctrl+C to leave debug repl
> i
1
> currentStudent
'Max'

 

Это тоже выглядит правильно. Мы собираемся быстро перейти к 6-й итерации нашего цикла for, где currentStudent должно быть ‘Dennis’.

debug> repl
Press Ctrl+C to leave debug repl
> i
5
> currentStudent
'Dennis'

 

Все i и currentStudent были такими, как ожидалось, на каждой итерации. Мы все еще не достигли undefined currentStudent. Если мы снова пройдемся по коду, мы бы ожидали, что функция завершится, когда мы дойдем до последнего пользователя в нашем массиве allStudents.

debug> cont
break in index.js:7
  5   for (let i = 0; i <= array.length; i++) {
  6     const currentStudent = array[i];
> 7     debugger;
  8     const firstLetter = currentStudent[0];
  9     if (firstLetter === "A") {
debug> repl
Press Ctrl+C to leave debug repl
> i
6
> currentStudent
undefined

 

Но это не то, что произошло. Здесь отладчик узла показал нам, что в нашем цикле for осталась еще одна итерация, из-за чего i of 6 вышел за пределы. Вот почему currentStudent[0] было не определено – потому что нет currentStudent индекса равного 6. Мы можем исправить наш код, удалив = из нашего условия цикла for .

const allStudents = ["AndreyEx", "Max", "Alex", "Dasha", "Anna", "Dennis"];

function startsWithJ(array) {
  const aStudents = [];
  for (let i = 0; i < array.length; i++) {
    const currentStudent = array[i];
    const firstLetter = currentStudent[0];
    if (firstLetter === "A") {
      aStudents.push(currentStudent);
    }
  }
  return aStudents;
}

startsWithJ(allStudents);
// => [ 'AndreyEx', 'Alex', 'Anna' ]

 

Отладчик узлов – отличный инструмент для проверки и отладки вашего кода, особенно если вы не хотите усложнять свой код инструкциями console.log().

 

Отладчик Chrome Developer Tools

Инструменты разработчика Chrome предлагают другой инструмент отладки, который вы можете использовать, если к вашему файлу JavaScript подключен HTML-файл. Вы можете создать базовый HTML-файл, единственной целью которого является вложение вашего JS-файла. Мы прикрепили файл JS, включив следующую строку в свой HTML-файл:

<script type="text/javascript" src="index.js"></script>.

 

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

const allStudents = ["AndreyEx", "Max", "Alex", "Dasha", "Anna", "Dennis"];

function startsWithJ(array) {
  {const aStudents = [];
    for (let i = 0; i < array.length; i++) {
      const currentStudent = array[i];
      const firstLetter = currentStudent[0];
      if (firstLetter === "A") {
        aStudents.push(currentStudent);
      }
    }
  }
  return aStudents;
}

startsWithJ(allStudents);

 

Читать  Этапы компилятора

Мы собираемся открыть HTML-страницу в Chrome, затем получить доступ к инструментам разработчика, нажав F12.

У Dev tools есть своя консоль, которая сразу показывает нам ошибку: Uncaught ReferenceError: jStudents is not defined. Это происходит в конце нашего кода, куда мы пытаемся вернуться jStudents. Точно так же, как и в случае с инструментом отладки узла, я собираюсь поместить в свой код инструкцию debugger, где мы хотим сделать паузу и рассмотреть поближе. Мы поместим ее в начало моей функции.

function startsWithJ(array) {
  {const aStudents = [];
    debugger; //ДОБАВЛЕНА СТРОКА
    for (let i = 0; i < array.length; i++) {
      const currentStudent = array[i];
      const firstLetter = currentStudent[0];
      if (firstLetter === "A") {
        aStudents.push(currentStudent);
      }
    }
  }
  return aStudents;
}

 

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

Если вы посмотрите направо, вы должны увидеть значения ваших переменных и информацию в стеке вызовов. Мы можем заглянуть сюда, чтобы увидеть, как меняются значения наших переменных (например aStudent) по мере выполнения кода. Вместо ввода cont в командной строке debug терминала, приятный пользовательский интерфейс инструмента отладки Chrome позволяет нам нажимать кнопки для пошагового выполнения кода.

Вы должны видеть значения currentStudentfirstLetteri и aStudent, которые будут изменяться по мере прохождения итераций.

Быстрая переадресация к последней итерации, aStudents назначена правильно ['AndreyEx', 'Alex', 'Anna']. Мы знаем, что наш цикл for работает должным образом. Но когда мы продолжим пошаговое выполнение каждой строки и выйдем из цикла for, вы заметите, что aStudents это исчезло с нашей вкладки scope. aStudents ранее была указана как переменная уровня блока, что предполагает, что она могла быть случайно объявлена в области видимости, к которой у нас больше нет доступа.

При более внимательном рассмотрении нашего кода мы можем видеть, что наш оператор return находится за пределами блока кода ({}), где был объявлен aStudents. Чтобы решить нашу проблему, мы можем поместить объявление переменной и оператор return в одну область видимости, удалив ненужное {}.

function startsWithJ(array) {
  const aStudents = [];
  debugger; //ДОБАВЛЕНА СТРОКА
  for (let i = 0; i < array.length; i++) {
    const currentStudent = array[i];
    const firstLetter = currentStudent[0];
    if (firstLetter === "A") {
      aStudents.push(currentStudent);
    }
  }
  return aStudents;
}

startsWithJ(allStudents);
// => [ 'Alex', 'Anna', 'Dennis' ]

 

Подведение итогов

Отладчик Chrome – наш личный фаворит из этих опций. Мы ценим, что нам не нужно вычищать кучу console.log(), когда мы закончим, и мы думаем, что это намного более интуитивно понятно в использовании, чем отладчик Node. Любой из этих способов допустим для отладки вашего кода. Возможно, вы даже захотите изучить возможность использования отладчика, встроенного в вашу среду разработки IDE.

Теперь у вас есть инструменты для устранения ваших ошибок и тщательного изучения вашего кода. Спасибо за чтение и удачи!

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (1 оценок, среднее: 5,00 из 5)
Загрузка...
Поделиться в соц. сетях:


0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

**ссылки nofollow

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии

Это может быть вам интересно


Рекомендуемое
Терминал Linux - это мощный инструмент, позволяющий пользователям взаимодействовать с…

Спасибо!

Теперь редакторы в курсе.