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




Порой написание кода 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 рекомендует:




К сожалению, не доступен сервер mySQL