Skip to content

Latest commit

 

History

History
352 lines (245 loc) · 34.2 KB

chapter-11-tricks-and-hacks.md

File metadata and controls

352 lines (245 loc) · 34.2 KB

Глава 11. Хитрости и хакове

В настоящата глава ще разгледаме някои хитрости, хакове и техники, които ще улеснят работата ни с езика JavaScript в среда за разработка Visual Studio Code. По-специално ще се запознаем:

  • Как правилно да форматираме код.
  • С конвенции за именуване на елементи от код.
  • С някои бързи клавиши (keyboard shortcuts).
  • С някои шаблони с код (code snippets).
  • С техники за дебъгване на код.

Форматиране на кода

Правилното форматиране на нашия код ще го направи по-четим и разбираем, в случай че се наложи някой друг да работи с него. Това е важно, защото в практиката ще ни се наложи да работим в екип с други хора и е от голямо значение да пишем кода си така, че колегите ни да могат бързо да се ориентират в него.

Има определени правила за правилно форматиране на кода, които събрани в едно се наричат конвенции. Конвенциите са група от правила, общоприети от програмистите на даден език, и се ползват масово. Тези конвенции помагат за изграждането на норми в дадени езици - как е най-добре да се пише и какви са добрите практики. Приема се, че ако един програмист ги спазва, то кодът му е лесно четим и разбираем.

Езикът JavaScript е създаден от Брендън Айх като част от развитието на един от първите браузъри Netscape. Основните конструкции и базов синтаксис преднамерено приличат на Java, за да се намалят усилията за научването им. Още повече, дори се използват подобни конвенции за писане и форматиране на кода. Трябва да знаете, че дори да не спазвате наложените конвенции, кодът ще работи (стига да е написан правилно), но просто няма да бъде лесно разбираем. Това, разбира се, не е фатално на основно ниво, но колкото по-бързо свикнете да пишете качествен код, толкова по-добре.

Правилата, които се ползват при писане на JavaScipt могат да бъдат намерени на много места. Официалните правила или т.н. JavaScript код конвенции са описана много добре в статията "Coding style" в документацията на "Mozilla": https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/Coding_Style. Важно е да се отбележи, че в примерите, които сме давали до сега и ще даваме занапред в тази книга, се ръководим основно от нея.

За форматиране на кода се препоръчва къдравите скоби {} да се отварят на същия ред и да се затварят точно под конструкцията, към която се отнасят, както е в примера по-долу.

if (someCondition) {
    console.log("Inside the if statement");
}

Вижда се, че командата console.log(…) в примера е 4 празни полета навътре (един таб), което също се препоръчва в документацията. Също така, ако дадена конструкция с къдрави скоби е един таб навътре, то къдравите скоби {} трябва да са в началото на конструкцията, както е в примера по-долу:

if (someCondition) {
   if (anotherCondition) {
       console.log("Inside the if statement");
   }
}

Ето това е пример за лошо форматиран код спрямо общоприетите конвенции за писане на код на езика JavaScript:

if(someCondition)
{
console.log("Inside the if statement");}

Първото, което се забелязва са къдравите скоби {}. Първата (отваряща) скоба трябва да е точно до if условието, a втората (затваряща) скоба - под командата console.log(…), на отделен празен ред. В допълнение, командата вътре в if конструкцията трябва да бъде 4 празни полета навътре (един таб). Веднага след ключовата дума if и преди условието на проверката се оставя интервал.

Същото правило важи и за for циклите, както и всякакви други конструкции с къдрави скоби {}. Ето още няколко примера:

Правилно:

for (let i = 0; i < 5; i++) {
    console.log(i);
}

Грешно:

for(let i=0;i<5;i++)
{
console.log(i);
}

За ваше удобство има бързи клавиши във Visual Studio Code, за които ще обясним по-късно в настоящата глава, но засега ни интересуват следните комбинации за форматиране на кода в целия документ:

  • За Windows [Shift + Alt + F]
  • За Mac [Shift + Option + F]
  • За Ubuntu [Ctrl + Shift + I]

Нека използваме грешния пример от преди малко:

for(let i=0;i<5;i++)
{
console.log(i);
}

Ако натиснем [Shift + Alt + F], което е нашата комбинация за форматиране на целия документ, ще получим код, форматиран според общоприетите конвенции за JavaScript. Автоматичното форматиране, обаче не влияе на именуването на нашите променливи, за което ние трябва да се погрижим сами. Прието е променливите да започват винаги с малка буква и да съдържат малки букви, като всяка следваща дума в тях започва с главна буква (това именуване е още познато като camelCase конвенция).

  • Трябва да се внимава за главни и малки букви, тъй като JavaScript прави разлика между тях. Например age и Age са различни променливи.
  • Имената на променливите не могат да съвпадат със служебна дума (keyword) от езика JavaScript, например let е невалидно име на променлива. Служебните или т.н. ключови фрази са просто думи, които са част от синтаксиса на JavaScript и поради тази причина те са резервирани и не могат да бъдат ползвани като имена на нашите променливи. Чрез тези думи ние имаме възможност да изграждаме нашите програми. Като пример за такива думи могат да се дадат вече използваните: for, while, do, if, else, let и др. Пълен списък с тези резервирани фрази можете да видите тук: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#Keywords
Въпреки че използването на символа _ в имената на променливите е разрешено, в JavaScript това не се препоръчва и се счита за лош стил на именуване.

Ето няколко примера за добре именувани променливи:

  • firstName
  • age
  • startIndex
  • lastNegativeNumberIndex

Ето няколко примера за лошо именувани променливи, макар и имената да са коректни от гледна точка на езика JavaScript:

  • _firstName (започва с '_')
  • last_name (съдържа '_')
  • AGE (изписана е с главни букви)
  • Start_Index (започва с главна буква и съдържа '_')
  • lastNegativeNumber_Index (съдържа '_')

Първоначално всички тези правила може да ни се струват безсмислени и ненужни, но с течение на времето и натрупването на опит ще видите нуждата от норми за писане на качествен код, за да може да се работи по-лесно и по-бързо в екип. Ще разберете, че е изключително досадна работата с код, който е написан без да се спазват никакви правила за качествен код.

Бързи клавиши във Visual Studio Code

В предната секция споменахме за някои от комбинациите, които се отнасят за форматиране на код. Едната комбинация [Shift + Alt + F] беше за форматиране на целия код в даден файл, а другите правиха същото нещо но на различна операционна система. Тези комбинации се наричат бързи клавиши и сега ще дадем по-подробна информация за тях.

Бързи клавиши са комбинации, които ни предоставят възможността да извършваме някои действия по-лесно и по-бързо, като всяка среда за разработка на софтуер си има своите бързи клавиши, въпреки че повечето се повтарят. Сега ще разгледаме някои от бързите клавиши във Visual Studio Code. Изброените клавишни комбинации работят със сигурност и са изпробвани на Windows. Идеята е да ви покажем, че това съществува, ползва се лесно и при нужда винаги можете да намерите, това което ви трябва за всяка една операционна система.

Комбинация Действие
[CTRL + F] Комбинацията отваря търсачка, с която можем да търсим в нашия код.
[CTRL + /] Закоментира част от кода и съответно премахва коментара от закоментиран код
[CTRL + Z] Връща една промяна назад (т.нар. Undo).
[CTRL + Y] Комбинацията има противоположно действие на [CTRL + Z] (т.нар. Redo).
[Shift + Alt + F] Форматира кода според конвенциите по подразбиране.
[CTRL + Backspace] Изтрива думата вляво от курсора.
[CTRL + Del] Изтрива думата вдясно от курсора.
[CTRL + K S] Запазва всички файлове в проекта.
[CTRL + S] Запазва текущия файл.

Повече за бързите клавиши във Visual Studio Code може да намерите тук: https://code.visualstudio.com/shortcuts/keyboard-shortcuts-windows.pdf.

Ако пък вече се чувствате достатъчно уверени в уменията си с бързите клавиши, отворете Visual Studio Code и натиснете [CTRL + K + S] (обърнете внимание, че е различно от [CTRL + K S], при което Ctrl и K се натискат едновременно, а S след това), при което ще се отвори прозорец в самата среда за разработка, който съдържа пълен списък с всички възможни клавишни комбинации в света на Visual Studio Code. Още повече, дори от там ще можете да правите промени по съществуващите клавишни комбинации:

Не се колебайте, приложите наученото сега и използвайте клавишните комбинации, които мислите, че ще ви спомогнат в писането на вашите програми!

Шаблони с код (code snippets)

Във Visual Studio Code съществуват т.нар. шаблони с код (code snippets), при изписването на които се изписва по шаблон някакъв блок с код. Тази полезна опция не е включена по подразбиране. Вие сами трябва да я активирате от [File -> Preferences -> Settings] (или просто [Ctrl + Comma]), при което ви се отваря прозорец наречен User Settings. Това са вашите лични настройки, които много лесно можете да промените. Просто добавете следния ред между отварящата и затварящата къдрави скоби в дясната част на екрана:

"editor.tabCompletion": true

След като направите това, при изписването на "for" и натискане на [Tab] + [Tab], автоматично се генерира кодът на цялостен for цикъл в тялото на нашата програма. Това се нарича "разгъване на шаблон за кратък код". Подобно работи и шаблона "if" + [Tab] + [Tab]. На фигурата по-долу е показано действието на шаблона "for":

Да си направим собствен шаблон за код

В тази секция ще покажем как сами да си направим собствен шаблон. Ще разгледаме как се прави code snippet за json обект. Като за начало ще отидем на [File -> Preferences -> User Snippets], след което ще се отвори прозорец, от който да си изберете за кой език за програмиране ще създавате шаблон, както е показано на снимката:

Избираме JavaScript от падащото меню и ще се отвори прозорец с наименуван javascript.json. Това разширение json е един специален формат на записване на данни, който е наложен при начините за пренос и запазване на данни. Освен това, json форматът може да се ползва и в нашите програми, както ще разгледаме малко по - късно. Файлът изглежда така:

Примерът, който виждаме по подразбиране генерира код за писане по конзолата чрез ключовия префикс log. Този код е само примерен и всъщност този шаблон е вграден, но ако не беше, би изглеждал като примера.

В този пример виждате доста непознати неща, но няма страшно, по-нататък ще се запознаем и с тях. Сега се фокусираме върху частта "Print to console": и кода между отварящата и затварящата къдрави скоби {}. Това, което виждаме вътре в скобите представлява съдържанието на един шаблон. Всеки шаблон трябва да съдържа prefix, който представлява краткия текст, който след като натиснете [Tab] + [Tab] ще създава кода на шаблона във вашата програма.

Второто нещо, което трябва да има вашият шаблон е body, това е най-сложната част от шаблона. Това всъщност е кодът, който ще се генерира, като в него може да използваме променливи, които се създават с $1, като на мястото на единицата може да бъде поставен друг текст. В примера е използвана променлива: "console.log('$1');".

Може да използваме Tabstops, които просто поставят курсора на определени места в кода и между тях може да се навигира с табулация. Те се създават автоматично чрез създаване на променлива. Може да използваме и Placeholders, те представляват вид Tabstops, но могат да съдържат и някаква стойност, например: ${1:myVal}.

Съществуват и по сложни конфигурации, но като за начало тези ще ни свършат отлична работа.

Последната част от шаблона е description, което служи за добавяне на допълнително пояснение за това, което прави той. Сега нека да пробваме да направим собствен шаблон. Изтриваме дадения пример и въвеждаме следния код:

Вече когато напишем json + [Tab] + [Tab] в отворен JavaScript файл във Visual Studio Code, нашият нов snippet се появява:

За тези от вас, които се интересуват повече от темата, доста от големите frameworks като Angular, React и др. имат собствени шаблони, които могат да се инсталират от прозореца за разширения (Extensions). Както самото име подсказва, framework представлява концептуална структура, която ни помага, като дава някои неща наготово, а също така и ни предпазва да не правим големи грешки, като налага някои ограничения. Основната идея е да дава завършено решение в дадена област, което да има възможност за надграждане на всички компоненти в тази област. Част от нещата, които можете да получите наготово са и именно тези шаблони.

Техники за дебъгване на кода

Дебъгването играе важна роля в процеса на създаване на софтуер, която ни позволява постъпково да проследим изпълнението на нашата програма. С помощта на тази техника можем да следим стойностите на локалните променливи, тъй като те се променят по време на изпълнение на програмата, и да отстраним евентуални грешки (бъгове). Процесът на дебъгване включва:

  • Забелязване на проблемите (бъговете).
  • Намиране на кода, който причинява проблемите.
  • Коригиране на кода, причиняващ проблемите, така че програмата да работи правилно.
  • Тестване, за да се убедим, че програмата работи правилно след нанесените корекции.

Visual Studio Code ни предоставя вграден дебъгер (debugger), чрез който можем да поставяме точки на прекъсване (или т.нар. breakpoints), на избрани от нас места. При среща на стопер (breakpoint), програмата спира изпълнението си и позволява постъпково изпълнение на останалите редове. Дебъгването ни дава възможност да вникнем в детайлите на програмата и да видим къде точно възникват грешките и каква е причината за това.

За да демонстрираме работа с дебъгера, ще използваме следната програма:

for (let i = 0; i < 100; i++) {
    console.log(i);
}

Ще сложим стопер (breakpoint) на метода console.log(…). За целта трябва да преместим курсора на реда, който печата на конзолата, и да натиснем [F9]. Появява се стопер (червената точка, точно преди цифрата на ред 3), където програмата ще спре изпълнението си:

За да стартираме програмата в режим на дебъгване, избираме [Debug] -> [Start Debugging] или натискаме [F5]:

След стартиране на програмата виждаме, че тя спира изпълнението си на ред 4, където сложихме стопера (breakpoint). Кодът на текущия ред се оцветява с жълт цвят и можем да го изпълняваме постъпково. За да преминем на следващ ред използваме клавиш [F10]. Забелязваме, че кодът на текущия ред все още не е изпълнен. Изпълнява се, когато преминем на следващия ред:

От прозореца Debug, който се отваря от [View -> Debug] или чрез клавишна комбинация [Ctrl + Shift + D], можем да наблюдаваме промените по локалните променливи.

Справочник с хитрости

В тази секция ще покажем накратко хитрости и техники от програмирането с езика JavaScript, част от които споменавани вече в тази книга, които ще са ви много полезни, ако ходите на изпит по програмиране за начинаещи.

Закръгляне на числа

При нужда от закръгляне можем да използваме един от следните методи:

  • Math.round(…) - приема 1 параметър - числото, което искаме да закръглим. Закръглянето се извършва по основното правило за закръгляване - ако десетичната част е по-малка 5, закръглението е надолу и обратно, ако е по-голяма от 5 - нагоре:
let number = 5.439;
console.log(Math.round(number));
// Tова ще отпечата на конзолата "5"
let secondNumber = 5.539;
console.log(Math.round(secondNumber));
// Tова ще отпечата на конзолата "6"
  • Math.floor(…) - в случай, че искаме закръглянето да е винаги надолу до предишното цяло число. Например, ако имаме числото 5.99 и използваме Math.floor(5.99), ще получим числото 5:
let numberToFloor = 5.99;
console.log(Math.floor(numberToFloor));
// Tова ще отпечата на конзолата 5
  • Math.ceil(…) - в случай, че искаме закръглянето да е винаги нагоре до следващото цяло число. Например, ако имаме числото 5.13 и използваме Math.ceil(5.13), ще получим числото 6:
let numberToCeil = 5.13;
console.log(Math.floor(numberToCeil));
// Tова ще отпечата на конзолата 6
  • Math.trunc(…) - в случай, че искаме да премахнем дробната част. Например, ако имаме числото 2.63 и използваме Math.trunc(2.63), ще получим 2:
let numberToTrunc = 2.63;
console.log(Math.floor(numberToTrunc));
// Tова ще отпечата на конзолата 2

Използвайте === вместо ==, както и !== вместо !=

Операторите == и != правят автоматично преобразование на сравняваната стойност или променлива, докато операторите === и !== не прави такова преобразование и ако двете стойности не са от един и същ тип - резултатът е false. Те (== и !=) правят сравнение на стойността и типа, което е по-точно и дори по-бързо. Нека да видим следния пример, чрез който да изясним какво се има в предвид под тип на данните:

[10] === 10    // false
[10] == 10    // true
"10" == 10     // true
"10" === 10    // false
 [] == 0     // true
 [] === 0     // false
 "" == false   // true but true == "a" is false
 "" === false // false 

Виждаме как числото 10 може да бъде записано в нашите програми по различни начини. Записано по този начин [10] представлява масив от едно число. Накратко масивите са множество стойности записани в дадена променлива. Например:

let array = [10, 20, 30, 40];
// Това e променлива от тип масив

В последствие ще научим повече относно масивите, но за сега нека само се замислим дали масивът [10] е нормално да е равен на числото 10. Ще ви подскажем - не е нормално. Затова, ако не искаме неприятни грешки (бъгове) във нашите програми, най-добре да ползваме операторите === и !==.

Ситуацията с останалите оператори за сравнения е подобна и същата логика важи и там.

Как се пише условна конструкция?

Условната if конструкция се състои от следните елементи:

  • Ключова дума if
  • Булев израз (условие)
  • Тяло на условната конструкция
  • Незадължително: else клауза
if (условие) {
    // тяло
}
else (условие) {
    // тяло
}

За улеснение при изписване, може да използваме шаблонът (code snippet) за if конструкция: if + [Tab] + [Tab]**

Как се пише for цикъл?

За for цикъл ни трябват няколко неща:

  • Инициализационен блок, в който се декларира променливата-брояч (let i) и се задава нейна начална стойност.
  • Условие за повторение (i <= 10).
  • Обновяване на брояча (i++).
  • Тяло на цикъла.
for (let i = 0; i <= 10; i++;) {
    // тяло
}

За улеснение при изписване, може да използваме шаблонът (code snippet) за for цикъл: for + [Tab] + [Tab]**

Използване на т.нар. положителни (Truthy) и отрицателни (Falsy) стойности

Всичките Truthy стойности използвани в условната конструкция if ще дадат положителен резултат и съответно нашата програма ще продължи изпълнението си в тялото на условната конструкция (за целите на примера тук тялото на условната конструкция не е форматирано правилно).

За част от тях изглежда логично да дават положителен резултат, но за други не чак толкова.

//Truthy
if (true) {}       //true
if ({}) {}         //true
if ([]) {}         //true
if (42) {}         //true
if ("foo") {}      //true
if (new Date()) {} //true
if (-42) {}        //true
if (3.14) {}       //true
if (-3.14) {}      //true
if (Infinity) {}   //true
if (-Infinity) {}  //true

Обратно, всички Falsy стойности, ще дадат отрицателен резултат и програмата няма да влезе в тялото на условната конструкция.

//Falsy
if (false) {}       //false
if (null) {}        //false
if (undefined) {}   //false
if (0) {}           //false
if (NaN) {}         //false
if ('') {}          //false
if ("") {}          //false

Не е необходимо тези стойности да се знаят наизуст на този етап, а само да се помни, че съществуват т.нар. Truthy и Falsy стойности. С времето ще свикнем как правилно да ги използваме и как да ни помагат, за да съкратим нашия код.

Какво научихме от тази глава?

В настоящата глава се запознахме как правилно да форматираме и именуваме елементите на нашия код, някои бързи клавиши (shortcuts) за работа във Visual Studio Code, шаблони с код (code snippets) и разгледахме как се дебъгва код.