[Перевод] Oops, I did it again: отладка распространенных ошибок в JavaScript

ef41ea9cf20de7ca2952a0b6e72fe4ab.png

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

Напоминаем: для всех читателей «Хабра» — скидка 10 000 рублей при записи на любой курс Skillbox по промокоду «Хабр».

Skillbox рекомендует: Практический курс «Мобильный разработчик PRO».


TypeError: свойство не определено

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.

Подробнее о свойствах можно почитать здесь.

Способы устранения ошибок 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 в данном контексте означает желание певицы, чтобы ей позвонили еще раз (здесь пояснение самого контекста песни, — прим. переводчика). Вполне может быть, что это желание приведет к повышению количества звонков в реальной жизни. Но в программировании это рекурсия, способная вызвать ошибку в случае переполнения стека вызовов.

Ошибки выглядят следующим образом:

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, но выполнение функции так и не завершится.

Если же начать надеяться на двух друзей, это снизит loneliness (одиночество), и звонка можно будет не ждать.

function oneMoreTime(stillBelieve=true, loneliness=0) {
    if (!stillBelieve && loneliness < 0) return
    loneliness--
    stillBelieve = false
    return oneMoreTime(stillBelieve, loneliness)
}


В качестве примера можно привести случаи с бесконечными циклами, когда система не выдает сообщение об ошибке, а страница, на которой выполняется JavaScript-код, просто зависает. Так случается, если у цикла 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) и здесь (для Firefox).

Ошибка в синтаксисе


Одна из наиболее распространенных ошибок в JavaScript — SyntaxError. Избежать их помогут расширения текстового редактора. Так, Bracket Pair Colorizer отмечает скобки в коде разными цветами, а Prettier или похожий инструмент анализа дает возможность быстро найти ошибки. Лучший вариант, чтобы снизить вероятность появления SyntaxError — минимальная вложенность.

Поделитесь в комментариях: что вы делаете для того, чтобы не допускать ошибок или быстро обнаруживать и ликвидировать их?

Skillbox рекомендует:

© Habrahabr.ru