Время на прочтение
8 мин
Количество просмотров 12K
Всем привет! Вдохновленные успехом предыдущей статьи, которая была написана в преддверии запуска курса «Fullstack разработчик JavaScript«, мы решили продолжить серию статей для новичков и всех тех, кто только начинает заниматься программированием на языке JavaScript. Cегодня мы поговорим об ошибках, которые случаются в JS, а также о том, как именно с ними бороться.
Отдебажь за человека одну ошибку, и он будет благодарен тебе один пулл реквест. Научи его дебажить самостоятельно, и он будет благодарен тебе весь проект.
Неизвестный тимлид
Типичные ошибки начинающих
Итак, начнем с самых примитивных ошибок. Допустим, вы только недавно закончили изучать основы HTML и CSS и теперь активно принялись за программирование на JavaScript. Для примера: вы хотите, чтобы при клике на кнопку у вас открывалось, к примеру, скрытое до этого момента модальное окно. Так же вы хотите, чтобы у вас по нажатию на крестик это окно закрывалось. Интерактивный пример доступен здесь (я выбрал bitbucket из-за того, что его интерфейс мне кажется самым простым, да и не все же на гитхабе сидеть).
let modal_alert = document.querySelector(".modal_alert")
let hero__btn = document.querySelector(".hero__btn")
let modal_close = document.querySelector(".modal-close ")
//мы выбрали из DOM модели наши элементы. К слову, я использую bulma для упрощения процесса верстки
//теперь мы хотим провести над нашими элементами какие-то операции:
hero__btn.addEventListener("click", function(){
modal_alert.classList.add("helper_visible");
})
modal_close.addEventListener("click", function(){
modal_alert.classList.remove("helper_visible");
})
//если мы хотим увидеть форму, то просто вешаем доп. класс, в котором прописано css-свойство display:flex. И наоборот, если хотим скрыть.
В нашем index.html, кроме верстки, мы внутри тэга head вставляем наш script:
<script src="code.js"></script>
В index.html
кроме верстки внутри тэга head
мы вставляем наш script
:
<script src="code.js"></script>
Однако, несмотря на то, что мы все подключили, ничего не заработает и вылетит ошибка:
Что весьма печально, новички часто теряются и не понимают, что делать с красными строчками, словно это приговор какой-то, а не подсказка о том, что не так в вашей программе. Если перевести, то браузер говорит нам, что он не может прочитать свойство addEventListener
нулевого значения. Значит, почему-то из DOM модели мы не получили наш элемент. Какой алгоритм действий нужно предпринять?
Во-первых, посмотрите в какой момент у вас вызывается javascript
. Браузер читает ваш html-код сверху вниз, как вы читаете, например, книгу. Когда он увидит тэг script
, то сразу исполнит его содержимое и продолжит чтение следующих элементов, не особо заботясь о том, что в своем скрипте вы пытаетесь получить элементы DOM, а он их еще не прочитал и, следовательно, не построил модель.
Что делать в таком случае? Просто добавьте атрибут defer
внутрь вашего тэга скрипт (или async
, но я не буду сейчас вдаваться в подробности их работы, это можно прочитать здесь ). Или можете просто переместить вниз ваш тэг script
перед закрывающим body
, это тоже сработает.
Во-вторых, проверьте опечатки. Изучите методологию БЭМ — она полезна ещё и тем, что вы хорошо знаете, как пишется ваш элемент — ведь пишите классы по единой логике, и стараетесь пользоваться только правильным английским языком. Или копируете сразу название элемента в JS файл.
Отлично. Теперь, когда вы поправили ошибки, можете насладиться рабочей версией кода по следующему адресу.
Загадочная ошибка
Больше всего новичков вводит в ступор странная ошибка последней строчки кода. Приведем пример:
В консоли выводится что-то непонятное. Если переводить, то буквально это «Неожиданный конец ввода» — и что с этим делать? Кроме того, новичок по привычке смотрит на номер строки. На ней вроде все нормально. И почему тогда консоль на нее указывает?
Все просто. Что бы понимать, как интерпретировать вашу программу, интерпретатору JS нужно знать, где заканчивается тело функции, и где заканчивается тело цикла. В данном варианте кода я абсолютно намеренно забыл последнюю фигурную скобку:
// тут у нас просто два массива с заголовками и статьями
let root = document.getElementById("root"); // реактно подобно использую root
let article__btn = document.querySelector("article__btn");
// при клике на кнопку прочитаем статью
article__btn.onclick = () => {
for (let i = 0; i < headers.length; i++) {
root.insertAdjacentHTML("beforeend", `
<div class="content is-medium">
<h1>${headers[i]} </h1>
<p>${paragraps[i]}</p>
</div>`)
//изъятие фигурной скобки выполнено профессионалами. Не повторять на продакшене
}
Теперь JavaScript не понимает, где у него конец тела функции, а где конец цикла и не может интерпретировать код.
Что делать в данном случае? В любом современном редакторе кода, если вы поставите курсор перед открывающей скобкой, подсветится его закрывающий вариант (если редактор еще не начал подчеркивать эту ошибку красным цветом). Просмотрите код еще раз внимательно, держа в голове, что в JS не бывает одиноких фигурных скобок. Проблемный вариант можно посмотреть здесь, а исправленный — вот тут.
Дробим код
Чаще всего стоит заниматься написанием кода, тестируя его работу небольшими кусочками.
Или как нормальный человек изучить TDD
К примеру, вам нужно простую программу, которая принимает данные на вход от пользователя, складывает их в массив и после этого выводит их средние значения:
let input_number = prompt("Введите количество переменных");
// определяем, какое количество переменных к нам придет
let numbers = [];
function toArray(input_number){
for (let i = 0; i < input_number; i++) {
let x = prompt(`Введите значение ${i}`);
numbers.push(x); // и складываем значения в массив
}
}
toArray(input_number);
function toAverage(numbers){
let sum = 0;
for (let i = 0; i < numbers.length; i++) {
sum += numbers[i];
}
return sum/numbers.length;
}
alert(toAverage(numbers));
На первый неискушенный взгляд, в данном коде вполне все нормально. В нем есть основная логика, раздробленная на две функции, каждую из которой можно применять потом отдельно. Однако опытный программист сразу скажет, что это не заработает, ведь из prompt
данные к нам приходят в виде строки. Причем JS (таков его толерантно-пофигистичный характер) нам все запустит, но на выходе выдаст настолько невероятную чепуху, что даже будет непросто понять, как мы дошли до жизни такой. Итак, давайте попробуем что-нибудь посчитать в нашем интерактивном примере. Введем допустим число 3 в количество переменных, и 1 2 3 в поле ввода данных:
Что? Чего? Ладно, это JavaScript. Поговорим лучше, как мы могли бы избежать такого странного вывода.
Надо было писать на Python, он бы по-человечески предупредил нас об ошибке
. Нам надо было после каждого подозрительного момента сделать вывод типа переменных и смотреть, в каком состоянии находится наш массив.
Вариант кода, в котором вероятность неожиданного вывода снижена:
let input_number = prompt("Введите количество переменных");
console.log(typeof(input_number));
let numbers = [];
function toArray(input_number){
for (let i = 0; i < input_number; i++) {
let x = prompt(`Введите значение ${i}`);
numbers.push(x);
}
}
toArray(input_number);
console.log(numbers);
function toAverage(numbers){
let sum = 0;
for (let i = 0; i < numbers.length; i++) {
sum += numbers[i];
}
return sum/numbers.length;
}
console.log(typeof(toAverage(numbers)));
alert(toAverage(numbers));
Иными словами, все подозрительные места, в которых что-то могло пойти не так, я вывел в консоль, чтобы убедиться, что все идет так, как я ожидаю. Конечно, данные console.log
— детские игрушки и в норме, естественно, нужно изучить любую приличную библиотеку для тестирования. Например эту. Результат этой отладочной программы можно увидеть в инструментах разработчика здесь. Как починить, я думаю, вопросов не будет, но если если интересно, то вот (и да, это можно сделать просто двумя плюсами).
Шаг вперед: осваиваем Chrome Dev Tools
Дебаг с использованием console.log
в 2019 — это уже несколько архаичная штука (но мы все равно ее никогда ее не забудем, она уже нам как родная). Каждый разработчик, который мечтает носить гордое звание профессионала, должен освоить богатый инструментарий современных средств разработки.
Попробуем починить проблемные места в нашем коде с помощью Dev Tools. Если нужна документация с примерами, всё можно прочитать вот здесь. А мы попробуем разобрать предыдущий пример с помощью Dev Tools.
Итак, открываем пример. У нас явно запрятался какой-то баг в коде, но как понять, в какой момент JavaScript начал что-то неправильно считать?
Правильно, оборачиваем эту радость тестами на тип переменной, это же очень просто
Идем во вкладку Sources в инструментах разработчика. Откройте файл code.js
. У вас будут 3 части: первая слева, в которой отображается список файлов и вторая — в которой у нас отображается код. Но больше всего информации мы сможете почерпнуть из третьей части снизу, в которой отображается ход выполнения нашего кода. Давайте поставим breakpoint
на 15 строчке (для этого надо щелкнуть по номеру строки в окне, где у нас отображается код, после чего у вас появится голубая метка). Перезапустите страницу, и введите любые значения в нашу программу.
Теперь вы можете вытащить из нижней панели debug
массу полезной информации. Вы обнаружите, что JS не особенно задумываясь над типом переменных
ведь статистические языки тупо лучше и нужно писать только на них, чтобы получать предсказуемо работающие и быстрые программы
складывает переменные в виде строки в наш массив. Теперь, осознав картину происходящего, мы можем принять контрмеры.
Учимся перехватывать ошибки
Конструкция try… catch встречается во всех современных языках программирования. Зачем эта синтаксическая конструкция нужна практически? Дело в том, что при возникновении ошибки в коде, он останавливает свое выполнение на месте ошибки — и все, дальнейшие инструкции интерпретатор не исполнит. В реально работающем приложении, из нескольких сотен строчек кода, нас это не устроит. И предположим, что мы хотим перехватить код ошибки, передать разработчику ее код, и продолжить выполнение дальше.
Наша статья была бы неполной без краткого описания основных типов ошибки в JavaScript:
- Error — общий конструктор объекта ошибки.
- EvalError — тип ошибки, появляющийся во время ошибок исполнения
eval()
, но не синтаксических, а при неправильном использовании этой глобальной функции. - RangeError — происходит, когда вы выходите за пределы допустимого диапазона в исполнении вашего кода.
- ReferenceError — происходит, когда вы пытаетесь вызвать переменную, функцию или объект, которых нет в программе.
- SyntaxError — ошибка в синтаксисе.
- TypeError — происходит при попытке создания объекта с неизвестным типом переменной или при попытке вызова несуществующего метода
- URIError — редко встречающий код, который возникает при неправильном использовании методов encodeURL и DecodeURL.
Здорово, давайте теперь немного попрактикуемся и посмотрим на практике, где мы можем использовать конструкцию try… catch. Сам принцип работы данной конструкции совсем простой — интерпретатор пытается исполнить код внутри try
, если получается — то все продолжается, словно этой конструкции никогда не было. А вот если произошла ошибка — мы ее перехватываем и можем обработать, к примеру, сказав пользователю, где именно он допустил промах.
Давайте создадим самый простой калькулятор (даже калькулятором его называть громко, я бы сказал:«исполнитель введенных выражений»). Его интерактивный пример можно найти здесь. Хорошо, давайте теперь посмотрим на наш код:
let input = document.querySelector("#enter");
let button = document.querySelector("#enter_button");
let result_el = document.querySelector("#result ");
button.onclick = () => {
try {
let result = eval(input.value); //пробуем, если все будет корректно, тогда catch не сработает
result_el.innerHTML = result;
} catch (error) {
console.error(error.name);
result_el.innerHTML = "Вы что-то не то ввели, молодой человек<br> Подумайте еще раз";
//можно пользователю объяснять, что он не прав, если он допустил ошибку
//хотя естественно пользователю лучше не давать эту возможность))
}
}
Если вы попробуете ввести корректное математическое выражение, то все сработает нормально. Однако попробуйте ввести некорректное выражение, к примеру, просто строку, тогда программа выведет пользователю соответствующее предупреждение.
Надеюсь, вы прочитаете еще статьи, в которых объясняются другие части перехвата ошибок, такие например, как эта , чтобы расширить свое понимание в отладке программ, и изучите другие синтаксические конструкции, такие как finally
, а также генерацию своих собственных ошибок.
На этом все. Надеюсь, эта статья оказалась полезна и теперь, при отладке приложений, вы будете чувствовать себя более уверенно. Мы разобрали типичные ошибки от самых элементарных, которые делают новички программирующие на JS всего несколько дней, до техники перехвата ошибок, которые применяют более продвинутые разработчики.
И по традиции, полезные ссылочки:
- Пишем собственный фреймворк для тестирования. Полезно для общего понимания стратегии тестирования.
- Полная документация по ошибкам, в том числе и экспериментальные фичи
- Невероятно полезная статья на MDN, которая описывает большинство проблем, которые возникают в начале разработки на JS: отладку, полифиллы, дебагер и многое другое
На этом все. Ждем ваши комментарии и приглашаем на бесплатный вебинар, где поговорим о возможностях фреймворка SvelteJS.
Типы ошибок
JavaScript — это обычный алгоритмический язык программирования. Поэтому принципы поиска и исправления ошибок,
предложенные в этой теме, подходят и для других языков.
Ошибки делятся на два типа:
- Синтаксические
- Алгоритмические
Синтаксические — это ошибки, которые нарушают правила написания программы. Из-за них код становится
непонятным браузеру. Поэтому скрипт перестаёт выполняться или вообще не запускается. Например — пропущенная
буква в названии переменной или функции, незакрытая скобка или кавычка.
При алгоритмических ошибках программа выполняется, но работает не так как нужно и производит не
те действия, которые ожидает от неё программист.
Поиск синтаксических ошибок
Если Вы неправильно написали имя переменной или функции, то об этом вы можете узнать с помощью средств
отладки, которые будут рассмотрены далее.
Неправильно расставить кавычки вообще маловероятно, потому что в
текстовых редакторах текст в кавычках обычно выделяется своим цветом.
Найти незакрытую скобку помогут текстовые редакторы для
программирования. Соответсвующие скобки обычно выделяются определённым цветом.
Это работает со всеми видами скобок.
Поиск алгоритмических ошибок
Искать алгоритмические ошибки намного сложнее, потому что
они никак не проявляются. Чтобы найти такую ошибку,
нужно выбрать значимое место скрипта. Это могут быть последние
строки программы, отдельной функции или другая важная чать программы.
Затем нужно ответить на два вопроса:
- Доходит ли выполнение программы до этого места?
- Какое значение имеют переменные, имеющие отношение к ошибке?
Ответы на оба вопроса вы получаете, если выводите на экран значения важных переменных в выбранном месте
программы.
Выполнение программы может не дойти до определённого места из-за того, что не выполняется условие в
операторе if. Поэтому нужно смотреть значения выражений в ближайшем операторе
if. Если в нём сравниваются переменные, то нужно вывести на экран значения этих
переменных перед оператором. А если сравниваются выражения, то вывести на экран значения этих выражений.
Если выполнение программы дошло до выбранного места, но программа работает неправильно, значит какая-то
переменная имеет не то значение, какое должна иметь. Когда вы поймёте, какая это переменная, то нужно отследить
как меняется её значение по ходу всего выполнения. Нужно внимательно посмотреть те строки кода, в которых она
получает новые значения. Если визуально найти ошибку не удалось, то можно после каждого изменения значения
выводить переменную на экран. Так Вы найдёте строку, в которой нарушается алгоритм программы.
Средства отладки JavaScript кода
В браузерах есть средства отладки, которые помогают найти и исправить ошибки в JavaScript коде.
Мы используем «Инструменты
разработчика» браузера FireFox, которые уже рассматривались
в теме про отладку CSS. Нам будут полезны две вкладки панели инструментов — «Консоль» и «Отладчик».
Консоль браузера используется не только для скриптов, поэтому в ней есть несколько кнопок, для включения и
отключения разного вида информации. Пока вы не разберётесь с ними,
лучше их все включить.
Если скрипт содержит синтаксическую ошибку, то информация
об этом выводится в консоль. Указывается строка, в которой
находится ошибка. Только номер строки не всегда совпадает с номером в редакторе. Но можно кликнуть на цифру
и откроется код скрипта. В нём номер будет совпадать.
В консоль можно вывести данные из скрипта. Текст или значения переменных. Для этого в JavaScript есть
метод console.log(). Пример:
+
9 |
let num = 10; console.log('значение равно ', num); |
Результат будет выглядеть так:
Справа указана строка, которая вывела эту информацию.
В консоль можно вывести не только переменные, но также массивы и объекты. Сначала они выводятся в свёрнутом
виде. Их можно развернуть и посмотреть все данные, которые они содержат. Удобно отображаются DOM-объекты,
то есть, элементы страницы. Пример:
10 |
var div = document.querySelector('div'); console.log(div); |
В консоли DOM-объект выглядит так:
Вкладка «Отладка» панели инструментов позволяет приостановить выполнение скрипта на любой строке и
посмотреть, какие значения имеют переменные на этом этапе. Вкладка разделена на три части. В левой части
показаны файлы, в которых содержатся скрипты.
Кликните на нужном файле и в средней части вкладки отобразиться код файла. Строки кода пронумерованы. Можно
кликнуть на номерах нужных строк и они будут выделены синим цветом. На этих строках выполнение скрипта будет
приостанавливаться. Такие строки называются точки останова. Они перечислены также в правой части вкладки.
Когда вы выбрали нужные строки, запустите страницу заново. Скрипт остановится на первой выбранной строке и
можно будет посмотреть, как выглядит страница в этот момент. Также можно узнать какие значения имеют
переменные. В правой части вкладки нужно нажать «+», написать имя переменной и нажать Enter. Затем можно
добавить другую переменную.
Когда Вы посмотрели всё, что нужно, переходите к следующей точке останова. Нажмите кнопку «Возобновить».
Скрипт продолжит выполнение, дойдёт до следующей выбранной строки и вновь остановится.
Таким образом проходятся все точки останова, пока скрипт не выполнится. Если выбранная строка находится
внутри цикла, то скрипт останавливается на каждой итерации. Когда Вы
нашли ошибку, не забудьте отменить точки останова, чтобы скрипт выполнялся как обычно.
Рассмотренный инструмент позволяет быстро отследить изменение значений переменных по ходу всей программы.
Он полезен, когда трудно понять, в какой части скрипта находится ошибка. Вы можете выбрать сразу несколько
строк и посмотреть, как ведёт себя программа в этих строках.
Если ваш веб-сайт перестает нормально работать, консоль браузера — это первое место, на которое вам следует обратить внимание для диагностики проблемы. В большинстве популярных браузеров консоль довольно легко найти. Но если вы никогда не отваживались на инструменты разработчика своего браузера, то поиск и исправление ошибок веб-сайта могут показаться вам немного непонятными, пока вы не прочитаете эту статью.
Содержание
1
Причины ошибок JavaScript
JavaScript замечательный, и у него есть много преимуществ, которые улучшают ваш сайт. На самом деле плагины на основе CMS, которые управляют многими магазинами электронной коммерции, используют JavaScript для интеграции всех видов функциональных возможностей, которые улучшают пользовательский опыт.
Но у JavaScript также есть несколько незначительных недостатков, главный из которых заключается в том, что одна ошибка JavaScript может привести к полной остановке всех других скриптов на странице. Так что, если вы используете какой-либо скрипт на основе CMS для своего сайта электронной коммерции, тогда другой плагин или расширение может нарушить JavaScript вашей платформы и наоборот. Проблемы могут возникнуть разные, трудно дать однозначный ответ заранее, поэтому главное — это понимать как диагностировать ошибки и научиться хотя бы понимать с чем они связаны.
Конечно, это означает, что посещения вашего сайта могут резко упасть, что может привести к снижению рейтинга в поисковых системах. Мы хотим помочь вам избежать этого. Поэтому воспользуйтесь приведенным ниже советом, чтобы найти и исправить распространенные ошибки JavaScript в браузере Chrome.
Консоль браузера и проверка ошибок JavaScript?
Если вы считаете, что проблема на вашем сайте вызвана ошибкой JavaScript, ваш браузер Chrome может легко это проверить. Вот как.
Шаг 1. Откройте консоль либо в виде отдельной панели, либо в виде ящика рядом с другой панелью.
У вас есть два варианта открытия панели консоли:
- Windows / Linux — Нажмите Ctrl + Shift + J.
- Mac — Нажмите Cmd + Opt + J.
У вас также есть два варианта открытия консоли в виде ящика рядом с другой панелью:
- Нажмите Esc при просмотре DevTools.
- Нажмите кнопку для настройки и управления DevTools, а затем нажмите Показать консоль.
Шаг 2: Теперь вы увидите данные, отображаемые в консоли. Вот пример на скриншоте.
Поиск распространенных ошибок JavaScript
Теперь, когда у вас есть открытая консоль, пришло время выяснить, какого черта мы смотрим, и посмотреть, есть ли какие-либо ошибки JavaScript.
Оставаясь на вкладке браузера, которую вы использовали для открытия консоли, перейдите на страницу, которую вы хотите проверить на наличие ошибок. Если вы уже находитесь на этой странице, перезагрузите ее, чтобы вы могли прочитать вывод консоли.
Если есть какие-либо ошибки JavaScript, вы увидите красную строку текста, указывающую на ошибку. Вы можете нажать на черную стрелку, чтобы развернуть ошибку и увидеть ее полную информацию в консоли. Если в JavaScript нет ошибок, вы не увидите красных линий или сообщений об ошибках.
Топ 10 самых распространенных ошибок JavaScript
Теперь давайте углубимся и обсудим некоторые наиболее распространенные ошибки JavaScript, с которыми вы можете столкнуться в Chrome, Safari и Internet Explorer.
1. Uncaught TypeError: Cannot read property. Невозможно прочитать свойство.
Эта ошибка возникает в Chrome при вызове метода или при чтении свойства для неопределенного объекта.
2. TypeError: ‘undefined’ is not an object (evaluating). ‘undefined’ не является объектом (оценка).
Эта ошибка возникает в Safari при вызове метода или при чтении свойства для неопределенного объекта.
3. TypeError: null is not an object (evaluating). null не является объектом (оценка).
Это еще одна ошибка Safari, возникающая при вызове метода или при чтении свойства для нулевого объекта.
4. (unknown): Script error. Ошибка скрипта.
Вы увидите эту ошибку, когда ошибка JavaScript, которая не была обнаружена, нарушает политику перекрестного происхождения и пересекает границы домена.
5. TypeError: Object doesn’t support property. Объект не поддерживает свойство.
Это ошибка Internet Explorer, возникающая при вызове неопределенного метода.
6. TypeError: ‘undefined’ is not a function. «undefined» не является функцией.
Эта ошибка возникает в Chrome, когда вызывается неопределенная функция.
7. Uncaught RangeError: Maximum call stack. Максимальный стек вызовов.
Это еще одна ошибка Chrome, которая может быть вызвана рядом сценариев.
8. TypeError: Cannot read property ‘length’. Невозможно прочитать свойство ‘length’.
Эта ошибка Chrome срабатывает, когда свойство длины чтения неопределенной переменной.
9. Uncaught TypeError: Cannot set property. Невозможно установить свойство.
Эта ошибка возникает, когда скрипт пытается получить доступ к неопределенной переменной. Без сбоев он вернется как «неопределенный», потому что невозможно установить или получить свойство неопределенной переменной.
10. ReferenceError: event is not defined. Событие не определено.
Эта ошибка JavaScript возникает, когда скрипт пытается получить доступ к неопределенной переменной или переменной, которая не входит в текущую область.
В большинстве случаев, если у вас есть плагин или скрипт, вызывающий эти ошибки JavaScript, обращение к разработчику за поддержкой приведет вас к решению. Как правило, они предоставляют исправление или просто выкладывают исправление со следующим обновлением плагина или скрипта.
Однако не всем нам так повезло, так как некоторые обновления и поддержка скриптов полностью прекращаются разработчиками по разным причинам. Они могут обанкротиться или перестать быть заинтересованными в поддержке проекта. Такое случается. Поэтому всегда полезно иметь кого-то в режиме ожидания, чтобы помочь, если вам неудобно самостоятельно устранять ошибки JavaScript.
Как решить проблему с javaScript
Поиск и исправление ошибок JavaScript на вашем веб-сайте электронной коммерции может оказаться сложной задачей даже с помощью простых шагов, которые мы предоставили выше. Однако, если вы подозреваете, что ошибки JavaScript мешают вашему сайту работать должным образом, важно как можно скорее устранить их, чтобы не потерять работоспособность сайта или его отдельных страниц.
Первым шагом попробуйте поискать решение и описание проблемы в интернете, зачастую во многом опыт решения таких ошибок уже присутствует на форумах и площадках где обсуждают различные технические вопросы сайтов. Во вторых попробуйте найти и решение и описание проблемы более детальнее. Возможно стоит определить строку кода где появляется проблема и что её вызывает на вашем сайте.
То есть по сути перед вами выбор: изучить и сделать самому или нанимать специалиста, который сделает исправление ошибок и решит вашу проблему.
Если вам критически нужна помощь в поиске и исправлении ошибок JavaScript или поддержке вашего сайта, свяжитесь с нами и я постараюсь помочь вам решить проблему.
Недавно мы рассказали о том, как начать писать программы на JavaScript:
- что такое HTML и JavaScript;
- из чего состоят скрипты;
- как и где их выполнять и куда вставлять;
- где искать готовые решения и что с ними потом делать;
- как работать с разными элементами и обрабатывать нажатия клавиш.
Теперь шагнём дальше — изучим отладку скриптов в браузере и посмотрим, чем она может нам помочь.
Что такое отладка
Отладка — это поиск и исправление ошибок в программе. Например, мы написали скрипт, добавили его на страницу, настроили запуск по нажатию кнопки — а при нажатии ничего не происходит. При этом в консоли нет никаких ошибок — все команды верные, браузер просто что-то делает, а результата нет. Отладка нужна как раз для того, чтобы найти ошибку и исправить её.
Варварская отладка
Самый примитивный вариант отладки — добавить в код на JavaScript метод console.log(), поместив в скобки нужные данные для отладки. Console.log() — это просто способ вывести в консоль какой-нибудь текст.
Например, внутри функции можно сказать: console.log(‘Вызвана такая-то функция’) — и в нужный момент мы увидим, что функция вызвалась (или нет).
Минус этого подхода в том, что в коде появляется много отладочного мусора. А ещё, если мы не предусмотрели логирование для какой-то функции, то мы не поймаем в ней ошибку.
К счастью, помимо console.log() человечество изобрело много удобных инструментов отладки.
Что нужно для отладки
Для несложных проектов на JavaScript проще всего использовать встроенный отладчик в браузере Google Chrome. Единственное ограничение — он работает только с файлами скриптов, а не со встроенным в страницу кодом. Это значит, что если код скрипта находится внутри HTML-файла внутри тега <script>, то отладка не сработает.
Чтобы открыть панель отладки в Chrome, нажимаем ⌘+⌥+I и переходим на вкладку Sources (Источники):
Открываем скрипт
Допустим, мы хотим посмотреть, как работает скрипт из задачи про выпечку и как он перебирает все варианты.
Всё, что у нас есть, — это код. Чтобы мы смогли его отладить, его нужно положить в отдельный файл скрипта, присоединить к HTML-документу и запустить в браузере.
Открываем любой текстовый редактор, например Sublime Text, вставляем код скрипта и сохраняем файл как temp.js. Имя может быть любым, а после точки всегда должно стоять js — так браузер поймёт, что перед нами скрипт.
После этого в новом файле вставляем шаблон пустой HTML-страницы и подключаем наш скрипт — добавляем в раздел <body> такую строку:
<script type="text/javascript" src="temp.js"></script>
Получиться должно что-то вроде такого:
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title></title>
</head>
<body>
<script type="text/javascript" src="temp.js"></script>
</body>
</html>
Сохраняем этот код как HTML-файл, например index.html, и кладём в ту же папку, что и скрипт. Теперь заходим в папку и дважды щёлкаем по HTML-файлу, чтобы открыть эту страницу в браузере:
На странице ничего нет, но нам нужна не страница, а скрипт, поэтому находим слева наш файл temp.js и нажимаем на него — откроется код скрипта. Теперь можно начинать отладку:
Добавляем точки остановки
Точка остановки — это место, в котором наш скрипт должен остановиться и ждать дальнейших действий программиста. Их ещё называют брейкпоинты, от английского breakpoint — точка, где всё останавливается.
Когда скрипт доходит до этой точки, он ставит скрипт на паузу. При этом все данные и значения переменных скрипта остаются в памяти — в них можно заглянуть.
Брейкпоинт нужен для того, чтобы выполнить скрипт по шагам, начиная с первой команды. Чтобы его установить, нажимаем на номер строки с первой командой — в нашем случае это строка 2:
Обновим страницу и увидим, что скрипт начал работу и остановился. Но он остановился не на второй строке, а на шестой — всё потому, что это первая строка в скрипте, где происходит какое-то действие. Дело в том, что просто объявление новых переменных не влияет на работу скрипта, поэтому он ищет первую команду с действием. В нашем случае — это цикл for:
Пошаговая отладка
Чтобы посмотреть на работу скрипта по шагам, надо нажимать F9 или стрелку вправо с точкой на панели отладки:
Каждый раз, как мы будем нажимать F9 или эту кнопку, скрипт будет переходить к следующей команде, выполнять её и снова становиться на паузу:
Добавляем переменные для отслеживания
Если просто выполнять скрипт по шагам, то мы увидим, какие команды и в каком порядке выполняются, но не будем знать, какие значения лежат в переменных на каждом шагу. Их можно увидеть, просто наведя курсор на любую переменную — над ней появится всплывающая подсказка с текущим значением. Но так работать неудобно — проще сразу видеть значения всех переменных.
Чтобы добавить переменную и видеть её значение во время выполнения, в панели отладки в разделе Watch нажимаем плюсик, вводим имя переменной, выбираем её из списка и нажимаем энтер:
Теперь видно, что на этом шаге значение переменной a равно нулю:
Точно так же добавим остальные переменные: i, b, c. Так мы увидим, что первые два цикла только начались, а внутренний прошёл уже три итерации:
Так, нажимая постоянно F9, мы прогоним весь скрипт до конца и посмотрим, при каких значениях какие условия выполняются и как находится решение:
Но у такого подхода есть минус — если вложенных циклов много или скрипт очень большой, то на пошаговое выполнение уйдёт много времени. Чтобы не перебирать всё вручную, ставят дополнительные брейкпойнты в нужных местах.
Отладка брейкпойнтами
Допустим, нам важно понять, в какой момент скрипт находит и выдаёт решение. Глядя в код, мы понимаем, что как только скрипт дошёл до команды console.log() — он нашёл очередное решение. Это значит, что мы можем поставить брейкпоинт только на эту строчку и не прогонять вручную весь скрипт: он сам остановится, когда дойдёт до неё, а мы сможем посмотреть значения переменных в этот момент.
Для этого:
- Нажимаем снова на строку 2 и убираем предыдущую точку остановки.
- Ставим брейкпоинт на строку 20 — там, где происходит вывод решения в консоль.
- Нажимаем F8.
После этого скрипт продолжит работу сам и снова остановится, как только дойдёт до этой строки. Обратите внимание на значения переменных — они меняются к каждой остановке, а значит, скрипт работает как обычно, но останавливается в нужном нам месте:
Таких точек остановки можно поставить сколько угодно и в любой момент — на каждой из них отладчик остановится и покажет текущее состояние скрипта.
Зачем это всё
Отладка нужна, чтобы найти ошибки в программе. Если мы видим, что на очередном шаге в переменной находится не то, что мы ожидали увидеть, значит, что-то в коде идёт не так. Мы ставим брейкпоинт на начало нужных команд, запускаем отладку и находим команду, которая приводит к ошибке.
В следующей статье мы покажем на примере с реальным кодом, как отладка помогает находить и исправлять такие ошибки. Подпишитесь, чтобы не пропустить это.
Вёрстка:
Кирилл Климентьев
Временами работа над кодом JavaScript заставляет чувствовать себя выдохшимся и измождённым, поэтому некоторые подсказки по отладке никогда не будут лишними. На примерах из песен мы постараемся разобрать типичные ошибки в коде на JS и способы, которыми их можно найти и устранить.
Свойство не определено
let girl = {
name: "Lucky",
location: "Hollywood",
profession: "star",
thingsMissingInHerLife: true,
lovely: true,
cry: function() {
return "cry, cry, cries in her lonely heart"
}
}
console.log(girl.named.lucky)
Этот код выдаёт ошибку «Uncaught TypeError: Cannot read property ‘lucky’ of undefined». Дело в том, что объект girl
не имеет свойства named
, хотя у него есть свойство name
. Поскольку свойство girl.named
не определено, мы не можем получить к нему доступ, то есть оно просто не существует. Если мы заменим girl.named.lucky
на girl.name
, то код вернёт нам «Lucky».
Свойство — некоторое значение, привязанное к объекту JavaScript. Почитать больше об объектах можно здесь (статья на английском языке).
Отладка ошибок TypeError
Ошибки типа TypeError появляются, когда вы пытаетесь выполнить действия с данными, которые не соответствуют нужному типу, например применяете .bold()
к числу, запрашиваете свойство undefined
или пытаетесь вызвать как функцию что-то, не являющееся функцией. Например, вы увидите такую ошибку, если вызовете girl()
, поскольку это объект, а не функция. В последнем случае вы получите «Uncaught TypeError: yourVariable.bold is not a function» и «girl is not a function».
Для отладки этих ошибок надо разобраться с переменными. Что такое girl
? И что такое girl.named
? Вы можете понять это изучая код, выводя переменные с помощью console.log
, используя команду debugger
или просто напечатав имя переменной в консоли. Удостоверьтесь, что вы можете манипулировать содержащимся в переменной типом данных. Если тип данных не подходит, модифицируйте его нужным образом, добавьте условие или блок try..catch
, чтобы контролировать выполнение операции, или используйте эту операцию на другом объекте.
Переполнение стека
Если верить авторам песни «Baby One More Time», слово «hit» в строчке «Hit me baby, one more time» означает «позвони», то есть Бритни хочет, чтобы её бывший позвонил ей ещё раз. Это, возможно, приведёт к ещё большему количеству звонков в будущем. По сути это рекурсия, которая может вызвать ошибку в случае переполнения стека вызовов.
Конкретные сообщения об ошибке зависят от браузера, но выглядят они примерно так:
Error: Out of stack space (Edge)
InternalError: too much recursion (Firefox)
RangeError: Maximum call stack size exceeded (Chrome)
Переполнение стека может произойти, если в рекурсии не предусмотрен базовый случай или если код никогда не обращается к этому случаю.
function oneMoreTime(stillBelieve=true, loneliness=0) {
if (!stillBelieve && loneliness < 0) return
loneliness++
return oneMoreTime(stillBelieve, loneliness)
}
В показанной выше функции stillBelieve
никогда не примет значение false, и поэтому мы раз за разом будем вызывать oneMoreTime
, увеличивая одиночество, и никогда не завершим выполнение функции.
Если же Бритни решит положиться на своих друзей, это уменьшит её одиночество, она перестанет верить, что можно вернуть отношения, и не будет больше ждать звонка от бывшего партнёра.
function oneMoreTime(stillBelieve=true, loneliness=0) {
if (!stillBelieve && loneliness < 0) return
loneliness--
stillBelieve = false
return oneMoreTime(stillBelieve, loneliness)
}
Есть похожие случаи с бесконечными циклами, когда система не выдаёт сообщение об ошибке, но вместо этого страница, на которой исполняется код, зависает. Это происходит в случае цикла while
без условия завершения.
let worldEnded = false
while (worldEnded !== true) {
console.log("Keep on dancin' till the world ends")
}
Исправить это можно примерно так же, как и предыдущий пример.
let worldEnded = false
while (worldEnded !== true) {
console.log("Keep on dancin' till the world ends")
worldEnded = true
}
Отладка бесконечных циклов и рекурсий
Для начала, если возникла проблема с бесконечным циклом, закройте вкладку, если вы пользуетесь Chrome или Edge, или окно браузера, если у вас Firefox. Затем просмотрите код: есть ли там что-то, что создаёт бесконечный цикл или рекурсию. Если ничего не обнаружили — добавьте в цикл или функцию команду debugger
и проверьте значение переменных на нескольких начальных итерациях. Если они не соответствуют ожидаемым, вы это обнаружите.
В приведённом выше примере стоило бы добавить debugger
самой первой строкой функции или цикла. Затем нужно открыть отладочную вкладку в Chrome и изучить переменные в Scope
. С помощью кнопки «next» можно проследить, как они меняются с каждой итерацией. Обычно это помогает найти решение проблемы.
Здесь можно найти руководство на английском языке по отладке с помощью Chrome’s DevTools, а здесь — для Firefox.
Ошибка синтаксиса
SyntaxError
— вероятно самая распространённая разновидность ошибок в JavaScript. Эти ошибки возникают, если вы не соблюдаете правила синтаксиса языка. Копируя посыл песни Бритни «Everytime», JavaScript говорит отсутствующим скобкам и кавычкам: «Вы нужны мне, крошки».
Соответствующие расширения текстового редактора помогут избежать ошибок. Bracket Pair Colorizer размечает скобки в коде разными цветами, а Prettier или другой инструмент статического анализа кода поможет быстро найти ошибки. Постарайтесь придерживаться правильной разметки и делайте блоки кода как можно короче и с минимальной вложенностью. Такой подход сильно облегчает отладку.
Теперь, вооружившись новыми навыками отладки, вы станете немного сильнее в JavaScript, чем были вчера.
Перевод статьи Oops, I did it again: A guide to debugging common JavaScript errors