Oops, I did it again: адладка распаўсюджаных памылак у JavaScript

Oops, I did it again: адладка распаўсюджаных памылак у JavaScript

Часам напісанне кода 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 не працуе, і дзяўчынка не функцыя, паколькі на самой справе выклікаецца аб'ект, а не функцыя.

Для таго, каб ухіліць памылкі, трэба вывучыць зменныя. Дык, што такое girl? А што такое girl.named? Даведацца гэта можна, калі прааналізаваць код, вывесці зменныя з дапамогай console.log з, камандай debugger або выклікам імя зменнай у кансолі. Трэба пераканацца, што ёсць магчымасць апераваць тыпам дадзеных, які змяшчаецца ў зменнай. Калі ён не падыходзіць, зменіце яго, напрыклад, дадайце ўмову або блок try..catch - і атрымаеце кантроль над выкананнем аперацыі.

Перапаўненне стэка

Калі паверыць аўтарам слоў песні Baby One More Time (гэта Брытні Спірс, ага), то слова hit у дадзеным кантэксце азначае жаданне спявачкі, каб ёй патэлефанавалі яшчэ раз (тут тлумачэнне самога кантэксту песні, — заўв. перакладчыка). Цалкам магчыма, што гэтае жаданне прывядзе да павышэння колькасці званкоў у рэальным жыцці. Але ў праграмаванні гэта рэкурсія, здольная выклікаць памылку ў выпадку перапаўнення стэка выклікаў.

Памылкі выглядаюць наступным чынам:

Error: Out of stack space (Edge)
InternalError: Mut recurso (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 рэкамендуе:

Крыніца: habr.com

Дадаць каментар