Глава 2
Структура на програма

И сърцето ми свети ярко червено обвито в мъглата на полупрозрачна обвивка, те трябва да ми вкарат 10-кубика JavaScript, за да ме накарат да се върна. (Аз реагирам добре на токсини в кръвта.) Човече, тези неща, са като удар право в моите топки!”

_why, Why's (Poignant) Guide to Ruby

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

Expressions and statements (Изрази и изявления)

В Глава 1 създадохме някои стойности и след това приложихме оператори върху тях, за да получим нови стойности. Създаването на стойности, като че ли е съществена част от всяка програма на JavaScript, но това е само една част.

Фрагмент от код, който произвежда стойност се нарича expression (израз). Всяка стойност, която е написана буквално (като 22 или "psychoanalysis") е израз. Expression в скоби е израз, който е бинарен оператор, когато се прилага към два израза или унарен оператор, когато се прилага към един израз.

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

Ако израз съответства на фрагмент от изречение, то изявлението в JavaScript съответства на пълно изречение в човешката реч. Програмата е просто списък с изявления.

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

edit & run code by clicking it
1; !false;

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

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

Променливи

Как една програма поддържа вътрешния си свят? Как запомня неща? Видяхме как се произвежда нова стойност от стари стойности, но това не променя старите стойности и новата стойност трябва да ги използва веднага отново иначе ще изчезне. За да се направи и задържи стойност, JavaScript предвижда нещо, което се нарича променлива.

var caught = 5 * 5;

И това ни дава нашия втори вид изявление. Специалната ключова дума var показва, че това изречение ще дефинира променлива. Var e последвана от името на променливата и ако искаме незабавно да му се даде стойност, от = оператора и израз.

Предното изявление създава променливата caught и я използва за да вземе размера на номера, който се произвежда, като се умножи 5*5.

След като променливата е определена, нейното име може да се използва, като израз. Стойността на такъв израз е стойността на променливата, която в момента притежава. Ето един пример:

var ten = 10;
console.log(ten * ten);
// → 100

Името на променливата може да бъде всяка дума, която не е запазена (например var). То не може да включва празни пространства. Цифрите могат да бъдат част от името на променливата - catch22 е валидно име, но името не трябва да започва с цифра. Името на променливата не може да включва пунктуация, с изключение на характерите $ и _.

Когато променливата има стойност, това не означава, че тя е свързана с тази стойност завинаги. Оператора = може да се използва по всяко време върху съществуващите променливи, като ги изключва от текущата им стойност и ги насочва към нова.

var mood = "light";
console.log(mood);
// → light
mood = "dark";
console.log(mood);
// → dark

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

Variables as tentacles

Нека разгледаме един пример. За да си спомните, колко долара ви дължи Луиджи, можете да създадете променлива и когато той връща обратно 35$, тази променлива ще ви даде нова стойност.

var luigisDebt = 140;
luigisDebt = luigisDebt - 35;
console.log(luigisDebt);
// → 105

Когато дефинирате променлива без да и дадете стойност, пипалото нищо няма да разбере и няма да свърши нищо. Ако попитате за стойността на една празна променлива, ще получите undefined.

Един единствен var може да дефинира множество променливи, но те трябва да бъдат разделени със запетая.

var one = 1, two = 2;
console.log(one + two);
// → 3

Ключови и резервирани думи

Думи с особен смисъл, като var са ключови думи и те не могат да се използват за имена на променливи. Има и редица други думи, които са “запазени за употреба” в бъдещите версии на JavaScript. И те са официално забранени за ползване, като имена на променливи, макар че в някои среди на JavaScript го позволява. Пълният списък на ключовите и резервирани думи е дълъг:

break case catch class const continue debugger
default delete do else enum export extends false
finally for function if implements import in
instanceof interface let new null package private
protected public return static super switch this
throw true try typeof var void while with yield

Не се притеснявайте ако не ги запомните, но не забравяйте, че това може да бъде проблем ако някоя променлива дефиниция не работи, както се очаква.

Заобикаляща среда

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

Функции

Много от стойностите предвидени в заобикалящата среда имат по подразбиране тип на функция. Функцията е част от програма увита в стойност. Тези стойности могат да бъдат приложени за да стартираме програма. Така например, в средата на браузъра, променливата alert притежава функция, която показва малък диалогов прозорец със съобщение. Тя се използва по следния начин:

alert("Good morning!");
An alert dialog

Изпълнението на функцията е да призовава, извиква или прилага. Може да извикате функция чрез поставяне на скоби след израз, който произвежда стойност функция. Обикновено директно ще използвате името на променливата, която притежава функцията. Стойностите между скобите са дадени на програмата в рамките на функцията. В примера, на alert, функцията използва string, който ние сме дали за да покаже текста в диалоговия прозорец. Стойностите дадени на функцията се наричат arguments (аргументи). Функцията alert се нуждае само от един от тях, но други функции може да се нуждаят от различен брой или видове аргументи.

Функцията console.log

Функцията alert може да бъде полезна като изходно устройство, когато експериментирате, но щракайки по всички онези малки прозорци, ще ви се качи на нервите. При последните примери ние използвахме console.log за изходните стойности. Повечето системи за JavaScript (включително всички съвременни уеб браузъри и Node.js) осигуряват функцията console.log, която пише своите аргументи, като текст на изходно устройство. В браузъра изходното място е в конзолата на JavaScript. Тази част от интерфейса на браузъра е скрита по подразбиране, повечето браузъри го отварят при натискане на F12 за Windows или на Mac при натискане на Command-Option-I. Ако това не работи търсете по менютата елемент наречен “web console” или “developer tools”.

Когато използвате примерите или свой собствен код, на страниците на тази книга, console.log ще бъде показан след примера, вместо на JavaScript конзолата на браузъра.

var x = 30;
console.log("the value of x is", x);
// → the value of x is 30

Въпреки, че имената на променливите не могат да съдържат точка характер, console.log очевидно има една. Това е така защото console.log не е обикновена променлива. Всъщност това е израз, който извлича log от стойността на consoleпроменливата. Ще разберете какво точно означава това в Глава 4.

Стойности за връщане

Показване на диалогов прозорец или писане на текст на екрана е страничен ефект. Много функции са полезни именно поради страничните ефекти, които произвеждат. Функциите могат също да произведат стойности и в този случай не е необходимо да имат страничен ефект за да бъдат полезни. Например Math.max взема произволен брой цифрови стойности и връща по-голямата.

console.log(Math.max(2, 4));
// → 4

Когато дадена функция произвежда стойност, на нея и се казва да върне (return) тази стойност. Всичко, което произвежда стойност не е израз в JavaScript, което означава, че извикването на функции може да се използва в рамките на по-големи изрази. Тука се извиква Math.min, което е обратното на Math.max и се използва, като допълнение към оператора плюс:

console.log(Math.min(2, 4) + 100);
// → 102

Следващата глава обяснява как да пишете свои функции.

prompt and confirm

Средата на браузъра поддържа и други функции освен alert, за изкачащи прозорци. Можете питате потребителя за OK/Cancel използвайки confirm. Той връща Булева стойност: true ако потребителя кликне върху OK и false ако потребителя кликне Cancel.

confirm("Shall we, then?");
A confirm dialog

Функцията prompt може да се използва, за да поискате “отворен” въпрос. Първият аргумент е въпросът, а вторият е текстът, с който потребителя отговаря. Ред от текста може да бъде въведен в диалоговия прозорец и функцията ще го върне този текст, като string.

prompt("Tell me everything you know.", "...");
An prompt dialog

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

Контрол на потока

Когато програмата ви съдържа повече от едно изявление, те се изпълняват, предсказуемо от горе на долу. Като надлежен пример, тази програма има две изявления. Първото пита потребителя за номер, а второто, което се изпълнява след това, показва квадрата на този номер.

var theNumber = Number(prompt("Pick a number", ""));
alert("Your number is the square root of " +
      theNumber * theNumber);

Функцията Number конвентира стойността в номер. Ние се нуждаем от това преобразуване, защото резултата на prompt е string стойност, а ние искаме номер. Има подобни функции, като String и Boolean, преобразуващи стойности от тези типове.

Тука е доста тривиално схематично представяне на правата за контрол на потока:

Trivial control flow

Условно изпълнение

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

Conditional control flow

Условното изпълнение се пише с if - ключова дума в JavaScript. В най-простия случай, ние искаме някакъв код да бъде изпълнен, ако и само ако даденото условие е изпълнено. Така например, в предишната програма, можем да искаме да покажем резултата на корен квадратен от дадено число, само ако се въведе реално число.

var theNumber = Number(prompt("Pick a number", ""));
if (!isNaN(theNumber))
  alert("Your number is the square root of " +
        theNumber * theNumber);

С тази промяна, ако въведете “сирене”, на изхода няма да бъде показан резултат.

Ключовата дума if изпълнява или прескача изявление в зависимост от стойността на булевия израз. Решаващия израз е написан след ключовата дума в скоби, следвани от изявлението за изпълнение.

Функцията isNaN е стандартна JavaScript функция, която връща true само ако даденият аргумент е NaN. Функцията Number връща NaN ако подадем string, който не представлява валиден номер. По този начин, условието се превежда до - “освен ако theNumber не е не-номер, направи това”.

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

var theNumber = Number(prompt("Pick a number", ""));
if (!isNaN(theNumber))
  alert("Your number is the square root of " +
        theNumber * theNumber);
else
  alert("Hey. Why didn't you give me a number?");

Ако имаме повече от два пътя от които да избираме, можем да използваме if/else “оковани” заедно. Ето един пример:

var num = Number(prompt("Pick a number", "0"));

if (num < 10)
  alert("Small");
else if (num < 100)
  alert("Medium");
else
  alert("Large");

Програмата първо ще провери дали num е по-малко от 10. Ако е така, то избира този път и ще изпише "Small" и приключва. Ако не е така, отива на пътя на else който съдържа втори if. Ако второто условие (< 100) е изпълнено, това означава, че броят е между 10 и 100 и се изписва "Medium". Ако и това не стане на последно място е пътя else, при който числото е по-голямо от 100.

Схемата на тази програма изглежда по следния начин:

Nested if control flow

While and do loops

Помислете за една програма, която отпечатва всички четни числа от 0 до 12. Един от начините да се напише това е :

console.log(0);
console.log(2);
console.log(4);
console.log(6);
console.log(8);
console.log(10);
console.log(12);

Това работи, но идеята за написването на една програма е да се направи нещо с по-малко работа, не повече. Ако имате нужда от всички четни числа до 1000, то предишното би било неефективно. Това което ни трябва е начин да се повтаря някакъв код. Тази форма на контрол на потока се нарича цикъл (loop):

Loop control flow

Цикъл контрола на потока ни позволява да се върнем в някакъв момент на програмата, където сме били преди и да я повторим с настоящата ни програма. Ако комбинираме с променлива, която има значение, можем да направим нещо такова:

var number = 0;
while (number <= 12) {
  console.log(number);
  number = number + 2;
}
// → 0
// → 2
//   … etcetera

В изявлението се започва с ключовата дума while, която създава цикъл. Думата while е последвана от израз, подобен на if в скоби и след това от изявление в фигурни скоби. Цикълът изпълнява това изявление докато израза произвежда стойност, която е true, когато се конвентира в булев тип.

В този цикъл искаме да отпечатаме и двете, текущия номер и добавянето на две към нашата променлива. Всеки път, когато трябва да изпълним няколко изявления вътре в цикъл, ние ги увиваме във фигурни скоби {}. Фигурните скоби направляват изявленията, както иска изразът в обикновените скоби: те ги групират заедно, правейки ги, като едно изявление. Поредицата от изявления поставени във фигурни скоби се нарича блок.

Много JavaScript програмисти поставят тялото на всеки цикъл или if в скоби. Те правят това за по-голяма съгласуваност и да не се налага да добавят или премахват скоби при промяна на броя на изявленията в тялото по-късно. В тази книга, аз ще пиша повечето единични изявления без скоби, тъй като ценя краткостта. Вие сте свободни да избирате, кой от двата стила предпочитате.

Променливата number показва начина, по който с дадена променлива може да следите напредъка на програмата. Всеки път когато цикълът се повтаря, number се увеличава с 2. След това, в началото на всяко повторение, тя се сравнява с броя 12 за да реши дали програмата е изпълнила цялата работа, която е възнамерявала да направи.

Като пример, че всъщност прави нещо полезно, сега ще напишем програма, която изчислява и показва стойността на 210 (2 на 10-та степен). Ще използваме две променливи: една да следи резултата и една да брои, колко често умножаваме този резултат по 2. Цикълът проверява дали втората променлива не е достигнала 10 и след това актуализира двете променливи.

var result = 1;
var counter = 0;
while (counter < 10) {
  result = result * 2;
  counter = counter + 1;
}
console.log(result);
// → 1024

Брояча може да започне от 1 и да проверява до <= 10, но по причини, които ще станат ясни в Глава 4, е добра идея да се използва да брои от 0.

Цикъла do е контролна структура, подобен на while цикъла. Той се различава само по една точка: един do цикъл винаги изпълнява блока в тялото си поне веднъж и започва да проверява дали трябва да спре едва след първото изпълнение. За да направи това, теста се поставя след тялото на цикъла:

do {
  var yourName = prompt("Who are you?");
} while (!yourName);
console.log(yourName);

Тази програма иска да въведете вашето име. Тя ще го иска отново и отново, докато не въведете нещо, което не е празен string. Прилагането на оператора ! ще превърне стойността в булев тип преди да я анулира и всички strings освен празни "" ще преобразува до true. Това означава, че цикъла ще продължава да се върти, докато не въведете нещо, което не е празен string.

Ред код

Вероятно сте забелязали празните пространства пред някои изявления. В JavaScript те не са задължителни - компютъра ще приеме програмата добре и без тях. В действителност, дори паузите в лините на програмите не са задължителни. Може да напишете програма, като една дълга линия, ако се чувствате добре с това. Ролята на нотацията вътре в блока е да направи структурата на кода да се откроява. В сложен код, където новите блокове са поставени в други блокове, може да стане трудно четима и да не се разбира, кога един блок свършва и започва друг. С подходяща нотация, визуалната форма на програмата съответства на формата на блоковете вътре в нея. Обичам да използвам две празни пространства за всеки отворен блок, но вкусовете се различават - някои използват четири празни пространства, други характерa за табулация.

for loops

Много цикли следват модела на while цикъла. Първо, се създава променлива “брояч”, за да следи напредъка на цикъла. След това идва while цикъл, чийто тест проверява дали брояча не е достигнал края. И в края на тялото на цикъла, брояча се актуализира.

Защо този модел се използва толкова често в JavaScript и други езици, малко по-късно, сега for loop.

for (var number = 0; number <= 12; number = number + 2)
  console.log(number);
// → 0
// → 2
//   … etcetera

Тази програма е точно еквивалентна на програмата по-рано. Единствената промяна е, че всички изявления, които са свързани със състоянието на цикъла, сега са групирани заедно.

Скобите, след ключовата дума for, трябва да съдържат две точки и запетя. Частта преди първата запетая инициализира цикъла, обикновено чрез дефиниране на променлива. Втората част е израз, който проверява дали цикъла трябва да продължи. В последната част се актуализира състоянието на цикъла след всяка итерация. В повечето случаи това е по-кратко и по-ясно, отколкото while конструкция.

Следва кода, който изчислява 210, като използва for вместо while:

var result = 1;
for (var counter = 0; counter < 10; counter = counter + 1)
  result = result * 2;
console.log(result);
// → 1024

Имайте в предвид, че въпреки, че блока не се отваря с {, изявлението в цикъла е по-навътре с две празни пространства, за да стане ясно, че "принадлежи" на линия преди него.

Прекъсване на цикъл

Когато цикълът работи, false не е единственият начин да се прекъсне. Има специална дума, наречена break, която има ефект за незабавно прекъсване и излизане от цикъла.

Тази програма илюстрира break. Тя намира първото число, което е едновременно по-голямо или равно на 20 и се дели на 7:

for (var current = 20; ; current++) {
  if (current % 7 == 0)
    break;
}
console.log(current);
// → 21

Използването на оператора (%) за остатък, е един лесен начин да се провери дали даден номер е делим от друг номер. Ако е така, остатъка от деленето е нула.

For цикъла в примера не разполага с една част, която проверява за край на цикъла. Това означава, че цикъла никога няма да спре, освен ако break изявлението не го прекъсне.

Ако не използвате break изявление или случайно напишете условие, което винаги произвежда true, вашата програма ще забие в един безкраен цикъл. А програма в безкраен цикъл никога няма да свърши, което обикновено е лошо нещо.

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

Continue е ключова дума подобна на break, която оказва влияние върху прогреса на цикъла. Когато се срещне continue в тялото на цикъла, контролирано се изкача от него и се продължава със следващата итерация на цикъла.

Актуализиране на променливи сбито

Има една особеност на цикъла, програмата често се нуждае от “обновяване” на променливата за да хване стойност на базата на предишната стойност:

counter = counter + 1;

JavaScript осигурява пряк път за това:

counter += 1;

Подобни преки пътища работят и за много други оператори, като result *= 2 за корен квадратен или counter -= 1 за броене на долу.

Това ни позволява да съкратим записа на примера малко:

for (var number = 0; number <= 12; number += 2)
  console.log(number);

За counter += 1 и counter -= 1, има още по-кратки еквиваленти: counter++ и counter--.

Dispatching on a value with switch

Това е общо за кода и изглежда така:

if (variable == "value1") action1();
else if (variable == "value2") action2();
else if (variable == "value3") action3();
else defaultAction();

Има конструкция наречена switch, която е предназначена за оптимизиране на такъв вид код по директен начин. За съжаление синтаксиса, който JavaScript използва за това (е наследила от C / Java езиците) е малко неудобен - верига от if изявления често изглежда по-добре. Ето един пример:

switch (prompt("What is the weather like?")) {
  case "rainy":
    console.log("Remember to bring an umbrella.");
    break;
  case "sunny":
    console.log("Dress lightly.");
  case "cloudy":
    console.log("Go outside.");
    break;
  default:
    console.log("Unknown weather type!");
    break;
}

Можете да поставите произволен брой case етикети вътре в блока на switch. Програмата ще отиде на етикета, който съответства на стойността, която е дадена на switch или default ако не намери съответна стойност. Switch започва да изпълнява отчети там, дори ако са под друг етикет, докато не достигне break изявление. В някои случаи като например "sunny" в примера, това може да се използва за споделяне на код между случаите (програмата препоръчва да се излезе на вън, както при слънчево така и при облачно време). Но внимавайте: може лесно да се забрави break, което ще доведе до изпълнение на код, който не искате да бъде изпълнен.

Капитализация

Имената на променливите не могат да съдържат интервали, но често е полезно използването на няколко думи за по-ясно описване, какво представлява променливата. Има доста начини за писане на име на променлива, ето няколко от тях:

fuzzylittleturtle
fuzzy_little_turtle
FuzzyLittleTurtle
fuzzyLittleTurtle

Първият стил е труден за четене. Лично аз, като гледам долните, ми се струва, че този стил е безполезно да се пише. Стандартните функции на JavaScript, както и повечето програмисти, следват долните стилове, като се възползват от всяка дума. Не е трудно да се свикне с малките неща, като това. Код със смесени стилове на именуване може да бъде шокиращ за четене, така че просто следвайте тази конвенция.

В няколко случая, като например функцията Number, първата буква на променливата също с главна буква. Това е направено за да се отбележи тази функция, като конструктор. Какво е конструктор ще стане ясно в Глава 6. За сега не трябва да се притесняваме от тази очевидна липса на съгласуваност.

Коментари

Често суровия код не предоставя цялата информация, която искаме програмата да предаде на евентуален друг читател или я предава по такъв загадъчен начин, че хората не могат да я разберат. В други случаи, може би ако се почувствате настроени поетично или искате да включите някои мисли, като част от вашата програма. Може да използвате коментарите за това.

Коментара е текст, който е част от програмата, но напълно се пренебрегва от компютъра. В JavaScript има два начина за писане на коментари. За да напишете коментар на един ред, може да използвате две наклонени черти (//) и след тях текста на коментара:

var accountBalance = calculateBalance(account);
// It's a green hollow where a river sings
accountBalance.adjust();
// Madly catching white tatters in the grass.
var report = new Report();
// Where the sun on the proud mountain rings:
addToReport(accountBalance, report);
// It's a little valley, foaming like light in a glass.

Този вид // коментар е само до края на линията. Ако текста се постави между /* и */ той ще бъде игнориран, независимо колко е голям или дали съдържа нови редове. Това често е полезно за добавяне на блокове от информация за даден файл или парче от код.

/*
 I first found this number scrawled on the back of one of
 my notebooks a few years ago. Since then, it has often
 dropped by, showing up in phone numbers and the serial
 numbers of products that I've bought. It obviously likes
 me, so I've decided to keep it.
*/
var myNumber = 11213;

Резюме

Вече знаем, че една програма е изградена от изявления, които понякога се съдържат в други изявления. Изявленията са склонни да съдържат изрази, които от своя страна могат да бъдат изградени от по-малки изрази.

Поставянето на изявления едно след друго, се изпълняват от програмата от горе на долу. Можете да въведете прекъсвания в потока за контрол, чрез използване на условия:(if, else, и switch) и цикли (while, do, и for).

Променливите могат да бъдат използвани, за да се подадат парчета от данни под едно име и са полезни за проследяване на състоянието на програмите. Заобикалящата среда е набор от променливи, които са дефинирани. Системата на JavaScript винаги поставя редица полезни стандартни променливи във вашето обкръжение.

Функциите са специални стойности, които оформят парче от програма. Може да се позовавате на тях, като пишете function Name(argument1, argument2). Извикана такава функция е израз и може да даде стойност.

Упражнения

Ако не сте сигурни как да пробвате вашите решения на упражненията на страниците на тази книга, прочетете въведението.

Всяко упражнение започва с описание на проблема. Прочете го и се опитайте да решите задачата. Ако се сблъскате с проблеми, може да прочетете помощта след упражнението. Пълни решения на упражненията не са включени в книгата, но може да ги намерите онлайн на адрес eloquentjavascript.net/code. Ако искате да научите нещо от упражненията, аз ви препоръчвам да прегледате решенията само след като сте решили задачата или най-малко, след като сте мислили и опитвали да я решите достатъчно дълго, за да имате леко главоболие.

Цикъл триъгълник

Напиши цикъл, който прави седем извиквания на console.log и произвежда следния триъгълник:

#
##
###
####
#####
######
#######

Може да ви бъде полезно, да знаете, че можете да намерите дължината на string с написването на .length след него.

var abc = "abc";
console.log(abc.length);
// → 3

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

// Your code here.

Може да започнете с една програма, която просто отпечатва числата от 1 до 7, които могат да се извлекат с няколко модификации на примера за отпечатване на четни числа показан по-рано в тази глава, където въведохме for цикъла.

Сега помислете за еквивалентността между номера и string характери. Може да преминете от 1 към 2 чрез добавяне на 1 (+= 1). По същия начин, може да се премине от "#" към "##" чрез добавяне на знак (+= "#"). По този начин, вашето решение ще следи отблизо програмата за брой-печат.

FizzBuzz

Напишете програма, която използва console.log за отпечатване на всички числа от 1 до 100, с две изключения. За номера, кратни на 3 - да печата "Fizz", а за номера кратни на 5 - да печата "Buzz" вместо тях.

Когато това проработи, променете програмата си да отпечатва "FizzBuzz" за номера, които са неделими на 3 и 5, като продължите да отпечатвате "Fizz" и "Buzz"

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

// Your code here.

Работата над цифрите е ясно, че е с цикъл, но избора какво да отпечатвате е въпрос на условно изпълнение. Помните ли трика с използване на оператора за остатък (%), който проверява дали даден номер се дели на друг номер (има остатък нула).

В първата версия, има три възможни изхода за всеки номер, така че трябва да се създаде if/else if/else верига.

Втората версия на програмата има едно ясно и хитро решение. Най-простият начин е да се добави още една “branch” на веригата за точно тестване на дадено състояние. Хитрия начин е изграждане на string съдържащ думата или думите на изхода и принтиране на тази дума или номер, ако потенциално няма дума, като използваме елегантно оператора ||.

Chess board

Напишете програма, която създава string, който представлява 8 х 8 решетка, използвайки знаците за нов ред за отделяне на линии. На всяка позиция на решетката има интервал или “#”. Характерите трябва да сформират шахматна дъска.

Минавайки този string през console.log трябва да покаже нещо такова:

 # # # #
# # # #
 # # # #
# # # #
 # # # #
# # # #
 # # # #
# # # #

Когато направите програмата, която генерира този модел, дефинирайте променлива size = 8 и променете програмата, така че да работи за всички size, като генерира решетка по дадената ширина и височина.

// Your code here.

String може да бъде изграден, като се започне с един празен ("") и многократно се добавят характери. Характера за нов ред се изписва "\n".

Използвайте console.log да се запознаете с изхода на вашата програма.

За да работите в две измерения, ще ви трябват два вложени цикъла. Поставете фигурни скоби около телата на двата цикъла, за да се направи лесно видимо къде е началото и края. Опитайте се да направите правилно отстоянията на техните тела. Редът на циклите трябва да следва реда, по който се изгражда string (ред по ред, от ляво на дясно, от горе на долу). Така че, външният цикъл държи линиите, а вътрешния цикъл държи характерите за една линия.

Ще имате нужда от две променливи, с които да следите напредъка. За да знаете дали да сложите празно пространство или знак за диез в дадена позиция, може да тествате дали сумата от двата брояча в циклите е четна (% 2).

Прекратяване на ред чрез добавяне на характера за нов ред се случва, след като линията е изградена, така че трябва да направите това след вътрешния цикъл, но от вътрешната страна на външния цикъл.