View on GitHub

info

Материјали за курс из УВИТ-а на Математичком факултету Универзитета у Београду

УВИТ - Програмски језик ЈаваСкрипт

Владимир Филиповић

Структура ЈаваСкрипт програма

У овој секцији је дат опис синтаксно коректних структура језика ЈаваСкрипт.

Основни елементи језика ЈаваСкрипт

Овде ће бити речи о градивним блоковима које се користе за изградњу конструкција ЈаваСкрипта: Unicode знацима, тачка-зарезима, белинама, разликовању великих и малих слова, коментарима, литрералима, идентификаторима и резервисаним речима.

Unicode знаци

JаваСкрипт програми се записују коришћењем Unicode знакова. То значи да ћириличне и латиничне речи, (нпр. мићко или mićko) могу представљати имена променљивих. Исто тако, речи на кинеском, јапанском или арапском језику когу означавти променљиве.

Наравно, овакво именовање, иако је могуће, није баш уобичајено - постоје различите конвенције за писање ЈаваСкрипт програмског кŏда, а понекад и програмерски тим дефинише своја правила за писање програмког кода, која су обично базирана на некој од постојећих конвенција.

Напомена. Конвенције кодирања обихватају правила о именима, али и много других ствари: начин преламања текста, начин назубљивања кода, постављање белина итд. Разавојно окружење Visual Stdio Code, исто као и друга данас популарна развојна окружења, омогућава да се програмски код читаве датотеке форматира у складу са сетом конвенција избором једноставне команде Format document или коришћењем тастатурне скраћенице Alt+Shift+F.

Тачка-зарез

Синтакса ЈаваСкрипта је у великој мери подсећа на програмски језик C, па постоји много примера кода у којима се тачка-зарез налази на крају сваке наредбе.

Међутим, за разлику од језика C, тачке-зарези нису обавезни на крају наредбе, већ сам унос знака за прелазак у следећи ред (осим у ретким специјалним случајевима) означава да је завршена наредба у датом реду. Дакле, код ЈаваСкрипта није проблем ако програмски код не садржи тачку-зарез.

Наравно, програмери који интензивно користе (или су раније интензивно користили) програмске језике Јава, C, C++ или C# обично наставе са праксом коришћења тачке-зареза у ЈаваСкрипту - што није погрешно. Међутим, није погрешна ни пракса многих других програмера (обично оних који користе, или су користили, језике у којима тачка-зарез не фигурише као терминатор наредбе) да пишу програме избегавајући корипћење знака ;.

Белине

Белине су, исто ка о у С-у, знаци који не остављају приказ на излазу: размак (или бланко), знак за табулирање (или таб), знак за нову линију, итд. У језику ЈаваСкрипт, белине немају значење. Дакле, теоретски гледано, белине и нове линије се могу додавати птпуно слободно и без било каквих ограничења/правила.

Како изрека каже: “У теорији, нема разлике између теорије и праксе. Међутим, у пракси разлика постоји.”, то се у пракси препоручује поштовање прецизно дефинисаног програмског стила и коришћење belina на уобичајен начин, уз коришћење алата као што су linter и Prettier.

Разликовање великих и малих слова

У језику ЈаваСкрипт се разликују велика и мала слова, па нпр. променљива osoba се разликује од Osoba, од osoBA и од osOba.

Ово правило, наравно, важи за све идентификаторе, а не само за променљиве.

Коментари

У ЈаваСкрипту се могу, аналогно као у С++ и Јави, користити две врсте коментара:

Литерали

Литерал је низ знакова који представља вредност уписану у самом изворном кŏду нпр. број, ниска, логичка вредност или нека вредсност са сложеном струкутром, као што су објектни литерали или низовни литерали.

Пример. Неки литерали: 5 'jedna niska' true ['a', 'b'] {boja: 'crvena', oblik: 'paravougaonik'}

Идентификатори

Идентификатор (тј. име) је секвенца знакова која се може користити за идентификацију (тј. именовање) променљиве, функције или објекта.

Идентификатор почиње са словом, са знаком за долар $ или са подвлаком _. Идентификаторм може садржавати и цифре. С обзиром да ЈаваСкрипт користи Unicode знаке, слова могу бити слова различитих алфабета, чак и емотикони.

Пример. Коректни идентификатори су нпр.: Test test TEST _test Test1 $test

Резервисане речи

Као што само име каже, резервисане речи су резервисане за конструкције ЈаваСкрипт језика и не могу се користити у сврху која је другачија од прописане.

Листа резервисаних речи се ширила током времена, представљањем нових верзија ЈаваСкрипта. У овом тренутку, резервисане (понегде се још зову и кључне) речи су: break, do, instanceof, typeof, case, else, new, var, catch, finally, return, void, continue, for, switch, while, debugger, function, this, with, default, if, throw, delete, in, try, class, enum, extends, super, const, export, import, implements, let, private, public, interface, package, protected, static, yield

Напомена. Речи NaN, Infinity и undefined нису у списку резервисних речи, али се не препоручује њихово коришћење као идентификатора или у било ком смислу који се разликује од намене која им је иницијално дата. Ове речи представљају немутирајуће особине глобалног објекта и њихова вредност може само да се чита.

Пример. Наредба NaN = 42 је синтаксно коректна, њеним извршавањем се неће генерисати грешка, али се неће ни променити вредност за NaN. █

Типови и вредности

Информација да језик ЈаваСкрипт нема типова није тачна. Наиме, једној променљивој се могу доделити вредности различитих типова, али вредности које се додeљују имају свој тип.

Типови у ЈаваСкрипту се деле у две основне групе:

  1. Примитивни типови

  2. Објектни типови

Примитивни типови

Као што има само име каже, примитивни типови су најпростији. Вредности примитивног типа су непроменљиве, тј. немутирајуће. То значи да након стварања и чувања у меморији та вредност на датом месту се више не може мењати. Непромењива природа података примитивног типа и јесте разлог што је за поређење промењивих које садрже примитиван тип вредности, довољно да пореде само вредности.

Примитивни типови су:

као и два специјална типа:

Напомена. За разлику од програмског језика C, где је била допуштена измена садржаја ниске, у језику ЈаваСкрипт ниске су немутирајуће.

Вредности примитивног типа се у литератури често значавају појмом “примитивне вредности”.

Сада ћемо се детаљније позабавити примитвним вредностима различитих типова.

Бројеви

Ако се посматра интерна репрезентација бројева у језику ЈаваСкрипт, могло би се рећи да постоји један тип за бројеве, тј. да је сваки број у ствари број у покретном зарезу.

Бројевни литерал је број записан у програмском тј. изворном кŏду - у зависности од тога како је записан, то може бити целобројни литерал или литерал који представља број у покретном зарезу.

Пример. Бројевни литерали, тј. записи целих бројева и бројева у покретном зарезу:

/* Zapis broja u fiksnom zarezu */
42;

/* Zapis broja u fiksnom zarezu */
0x42 // 66;

/* Zapis broja u fiksnom zarezu */
5354576767321;

/* Zapis broja u pokretnom zarezu */
9.81;

/* Zapis broja u pokretnom zarezu */
.1234; // 0.1234

/* Zapis broja u pokretnom zarezu */
2.998e8; //2.998 * 10^8

Ниске

Ниска тип представља секвенцу знакова. У изворном кŏду она се дефинише помоћу ниска-литерала, који је ограничен апострофима или наводницима.

Ниска може садржавати и тзв. ескејп-секвенцу која се интерпретира приликом приказа ниске - нпр. ескејп-секвенца \n представља знак за крај линије. Исто као и у програмском језику C, скејп-секвенце починњу обрнутим слешом, тј. знаком \. Ове секвенце су корисне нпр. када наводник треба да се нађе у оквиру ниске коју ограничавају наводници, када апостроф треба да се нађе у оквиру ниске коју ограничавају апострофи и сл.

Пример. Записи ниски:

/* запис ниске */
" Trla baba lan, da joj prođe dan "

/* алтернативни запис ниске */
' Trla baba lan, da joj prođe dan '

/* коришћћење знака \ омогућава да се ниска пружа кроз више редова */
"Trla baba lan, \
da joj prođe dan "

/* коришћћење знака \ омогућава да се ниска пружа кроз више редова */
"Trla \
baba lan, \
da joj prođe \
dan "

/* ниска која садржи знак за крај линије */
" Trla baba lan,\n da joj prođe dan "

/* ниска која садржи секвенцу знакова "\n" */
" Trla baba lan,\"\\n\" da joj prođe dan "

/* ниска која садржи секвенцу знакова "\n" */
' Trla baba lan,"\\n" da joj prođe dan '

Новији начин записа ниски, назван шаблон за ниску, где се као ограничење користи обрнути апостороф (тј. знак `), је описан касније, у поглављу о изразима.

Логички тип

Податак логичког типа може имати тачно једну од следеће две вредности: тачно (записује са са true) и нетачно (тј. false). Велики број оператора поређења: ==, ===, <> итд. као резултат враћају логичку вредност.

Наредбе гранања (нпр. if наредба) и наредбе циклуса (као што је while наредба) користе логичке вредности да би одредиле даљи ток извршавања програма.

Контролне структуре за гранање и за циклусе нису превише строге: оне поред чисто логичких података (тј. вредности true или false), прихватају и податке других типова који се тумаче (интерпретирају) као тачни или као нетачни.

Вредности које се интерпретирају као нетачне су: 0, -0, NaN, undefined, null, '' и "". Све остале вредности се тумаче као тачне.

Специјални тип null

Вредност null представља специјану вредност која указује на непостојање (одсуство) вреднпости.

Сличан концепт постоји и у другим програмским језицима, нпр. null у језику C#, као и nil или None у језику Пајтон.

Спeцијални тип undefined

Вредност undefined указује да променљива још није иницијализована или да недостаје њена вредност.

Уобичајено је да undefined буде повратна вредност функције која не враће вредност. Поред тога, ако је приликом позива функције број аргумената у позиву мањи од броја параметара, тада ће на почетку извршавања функције вредност параметара којима није прослеђен аргумент бити undefined.

Провера да ли је дата променљива undefined се врши тако што се тип променљиве (добијен применом typeof оператора) упореди без конверзије типова (тј. применом оператора ===) са типом undefined.

Објектни типови

Све што није примитивни тип, то представља објектни тип.

Функције, низови и објекти су примери објектних типова. Свако од њих има своје специфичне карактеристике, али они истовремену наслеђују својства објектног типа - сви они имају особине и методе.

Вредност објектног (референтог) типа се чувају у делу меморије која се назива хип. За разлику од вредности примитивног типа, вредност референтног типа може да се мења током времена.

Додељивање референтне вредности промењивој извршава исту акцију као и код примитива: вредност заузима место у меморији, а промењиве се поставља тако да указује на то место у меморији. Међутим, додељивње постојеће промењиве новој промењивој не копира ту вредност на ново место у меморији, већ само подеси да “нова “променљива буде преусмерена тако да реферише на то исто “старо” место. Стога ће “стара” и “нова” променљива постати “везане”: након вредности једне (било “старе”, било “нове” променљиве), долази до промене обе промењиве, јер обе реферишу на исто место у меморији.

Због сложености и важности функција, низова и објеката, они ће бити обрађени касније, у посебним поглављима.

Као што је истакнуто при опису примитивних типова, постоје примитвни типови за ниске, бројеве и логичке вредности. Поред тога, у језгру ЈаваСкрипта постоје предефинисани тј. “уграђени” објекти чија су имена иста као имена простих примитива (мада називи почињу са великим словом!): String, Number и Boolean. Надаље, подаци примитивних типова током извршавања програма бивају по потреби “обавијени” тј. у лету се направи немутирајући објекат који садржи исту примитивну вредност, па се операција уместо над примитивном вредношћу изврши над вредношћу објекта-омотача. Аутоматско омотавање се најчешће дешава када програмер над примитивном вредношчу позове неку од метода доступних из објекта-омотача.

Променљиве

Променљиве су именоване локације у меморији у којима могу да се чувају подаци. Вредност променљиве може да се мења за време извршавања програма, па отуда и назив променљива.

Имена променљивих у ЈаваСкрипту се могу састојати од произвољне комбинације слова и бројева, али постоје нека правила:

Декларисање и дефинисање промењиве су два различита поступка. Декларација промењиве је поступак стварања промењиве, тада се дефинише име промењиве и обезбедјује простор за њено складиштење, док је дефинисање промењиве поступак када се промењивој додељује нека вредност која се смешта у простор за складиштење.

Пример. Рад са променљивима:

// definicija promenljive
let prom = 5 * 5;

// prikaz vrednosti izraza koji sadrži promenljivu
let broj = 10;
console.log(broj * broj);

// promenljiva ne mora imati svo vreme istu vrednost
let raspolozenje = "Srećan \t :)";
console.log(raspolozenje);
raspolozenje = "Tužan \t :(";
console.log(raspolozenje);

// promenljiva se može uvećati i/ili umanjiti
let dug = 200;
dug -= 72;
console.log(dug);

// jednom naredbm se mogu definisati dve promenljive
let prva = 1, druga = 2;
console.log(prva + druga);

Пример. Независност при промени вредности променљивих:

// deklaracija i postavljanje vrednosti
let osoba1 = "Драгослав"
let osoba2 = "Драгослав"
// u ovom trenutku promenljive osoba1 i osoba2 imaju istu vrednost
console.log(osoba1)
console.log(osoba2)

// promena vrednosti promenljive osoba1 ne utice na osoba2
osoba1 = "Павле"
console.log(osoba1)
console.log(osoba2)

// promena vrednosti promenljive osoba2 ne utice na osoba1
osoba2 = "Никола"
console.log(osoba1)
console.log(osoba2)

// postavljenje vrednosti
osoba1 = "Драгослав"
osoba2 = osoba1
console.log(osoba1)
console.log(osoba2)

// promena vrednosti promenljive osoba1 ne utice na osoba2
osoba1 = "Павле"
console.log(osoba1)
console.log(osoba2)

Опсег и контексти

Једна од основних парадигми скоро сваког програмског језика је могућност чувања вредности у променљивим и каснијег преузимања или модификовања те вредности. У ствари, та способност складиштења вредности у и повлачења вредности из променљиве и даје стање програма.

Без таквог концепта, програм би могао да обавља неке задатке, али били би крајње ограничени и не баш занимљив.

Међутим, укључивање променљивих у наш програм отвара интересантна питања:

Ова питања говоре о потреби за добро дефинисаним скупом правила за чување променљивих на некој локацији, и за њихово касније проналажење. Тај скуп правила се назива опсег.

Појам опсегa промењиве (енгл. scope) је везан за појам промењиве и представља део програмског кŏда у којој је нека промењива доступна. Основна карактеристика опсега је граница тог опсега. У програмском коду, промењивој се може приступити само из њеног опсега тј. не може се приступити промењивој уколико се налазимо извршава код изван опсега те променљиве.

Поставља се још једно питање: где и како се постављају правила за опсег?

Разматрање опсега променљивих

Да би правилно схватили опсег, неопходно је имати глобалну слику о начину извршавања ЈаваСкрипт програма.

Упркос чињеници да ЈаваСкрипт спада у општу категорију „динамичког“ или „интерпетрианог“ језика, чињеница је да се и код њега прилоком извршавања врши превођење. Првођење се не врши дуго пре извршавања (као што је случај са језицима који се традиционално преводе) нити су резултати превођења преносиви између различитих дистрибуираних система - али фаза превођења се рализује при извршавању ЈаваСкрипт програма.

Приликом традиционалног процеса превођења, извршавају се следећа три корака:

1. Токенизација - разбијање низа знакова на смислене (за језик) делове, назване токени.

Пример. Размотритимо следећи програм, који садржи једну наредбу:

   var a = 2;

Овај програм би приликом токенизације вероватно био подељен на следеће токене: var, а, =, 2 и ;. Размак може или не мора бити чуван као токен, у зависности од тога да ли у контексту датог језика то има смисла или не. █

2. Парсирање - узима се ток (низ) токена и од њих се гради тзв. дрво апстрактне синтаксе (енг. abstract syntax tree) АСТ - дрво којe представља граматичку структуру програма.

Пример. Размотритимо програм из претходног примера.

   var a = 2;

Дрво апстрактне синтаксе за овај програм је дрво са кореном (тј. чвором највишег нивоа) названим VariableDeclaration, са једним потомком Identifier (чија је вредност а) и другим потомком AssignmentExpression, која сам има дете под називом NumericLiteral (чија је вредност 2). █

3. Генерисање кода - процес коришћења АСТ-а и претварања у извршни код.

Овај део се веома разликује у зависности од језика и платформе и то је ван фокуса овог излагања. Што се превођења у оквиру извршавања ЈаваСкрипт програма тиче, ЈаваСкрипт механизам превођења у току извршавања је много сложенији од три претходно наведена корака. На пример, у процесу парсирања и генерисања кода, свакако постоје кораци за оптимизацију перформанси, укључујући смањење сувишних елеменената итд.

Надаље, ЈаваСкрипт окружење за извршавање нема луксуз да имају много времена за оптимизацију, јер се код ЈаваСкрипта превођење не дешава у одовојеном кораку кораку пре извршавања, већ испреплетано са извршавањем.

Код ЈаваСкрипта, превођење се у многим случајевима дешава, само неку микросекунду (или краће!) пре него што се изврши преведени код. Да би се обезбедиле најбрже перформансе, ЈаваСкрипт машина користи све врсте расположивих техника и трикова.

За потпуно схватање рада са опсезима, неопходно је испратити интеракцију између следећих делова система:

Пример. Опет размотритимо програм из претходног примера.

   var a = 2;

Са програмерове тачке гледања, овај програм садржи једну операцију. Али, са становишта Машине, то није тачно. У ствари, Машина овде види две различите операције, једну коју ће реализовати Преводилац током компилације, и другу који ће реализовати Машина током извршавања.

Дакле, хајде да разјаснимо како ће делови система приступити извршавању горе наведног програма. Прва ствар коју ће Преводилац урадити са овим програмом је да га разбије на токене, које ће затим парсирати и добити дрво. Али, када дође до генерисања кода, Преводилац ће третирати овај програм нешто другачије него што се можда претпоставља.

Наиме, разумна претпоставка би била да ће Преводилац произвести код који би се могао сажето описати на следећи начин: „Додели меморију за променљиву, означити је са а, а затим смести вредност 2 у ту променљиву” и да ће Машина то реализовати. Нажалост, та претпоставка није сасвим тачна.

Уместо тога, интеракција се реализује на следећи начин:

  1. Наилазећи на var a, Преводилац тражи од Опсега да види да ли променљива а већ постоји за ту одређену колекцију опсега. Ако постоји, Преводилац игнорише ову декларацију и иде даље. Иначе, Преводилац тражи од Опсега да декларише нову променљиву која се зове а у тој колекцији опсега.

  2. Преводилац затим производи код за Машину који ће касније извршити и руковати са доделом а = 2. Том приликом Машину ће прво питати Опсег да ли постоји променљива која се зове а приступачна у тренутној колекцији опсега. Ако таква променљива постоји, Машина користи ту променљиву. Ако не, Машина тражи на другом месту (о чему ће бити више речи касније, при опису угнеждених опсега).

  3. Ако Машина на крају пронађе променљиву, додељује јој вредност 2. Ако не, она ће пријавити грешку!

Као што се може видети, да би се реализовала додела вредности промeнљиве, предузимају се две различите радње: Прво, Преводилац декларише променљиву (ако није претходно декларисана) у тренутном Опсегу, и друго, током извршавања, Машина тражи променљиву из Опсега и ако се пронађе та променљива додељује јој вредност. █

За даље разматрање ове теме, потребно је додатно упознавање са терминологијом.

Када Машина извршава код који је Преводилац произвео у другом кораку, она мора да потражи променљиву да види да ли та промељива је декларисана, а се реализује тако што се консултује Опсег. Међутим, тип претраживања утиче на исход потраге.

У претходном случају, тип претраживања који терба ивршити је претраживање леве стране (енг. left hand side - LHS). Постоји и друга врста потраге, која се назива потрага десне стране (енг. right hand side - RHS).

Код типова потраге, лева и десна страна се односе на позицију елемата који се тражи од Опсега у односу на доделу. Другим речима, тражење лева стране се врши када се променљива појави на левој страни доделе, а тражење десне стране се реализује када се променљива појави на десној страни доделе.

У овом контексту, могло би се рећи да се потрага десне стране не разликује ог једноставног прибављања вредности променљиве, док потрага леве стране покушава да пронађе контејнер за ту променљиву, како би се променљивој доделила вредност.

Пример. Размотритимо следећу наредбу:

   console.log(a);

Овде је референца на а референца десне стране, јер се променљивој а овде не додељује вредност, већ се тражи преузимање вредности за а како би се та вредност може приказати на конзоли.

За разлику од тога, другачија је ситуација код наредбе:

а = 2;

Референца на а овде је референца леве стране, јер није потребно да се одреди вредност за а, већ треба да се пронађеме променљива а као одредиште за операцију доделе = 2. █

Напомена. Лева и десна страна доделе не значе нужно лева и десна страна оператора доделе. Наиме, постоји неколико других начина да се изврши додела, па је зато је боље концептуално размишљати о левој страни доделе као одредишту, а о десној страни као извору приликом било какве (експлицитне, имплицитне) доделе.

Врсте опсега променљивих у ЈаваСкрипту

Према времену дефинисања, опсези дефинсаности се могу поделити на:

Према величини, опсези се могу поделити на:

Пре него што је уведена резервисана реч let, резервисана реч var се користила за декларисање променљиве. Променљива декларисана помоћу резервисане речи var није имала локални опсег дефинисаноти. Стога ће се променљиве декларисати помоћу var само у случају када је потребно да њихова вредност буде сачувана и послае “изласка” тока извршавања из блока у ком је таква променљива декларисана - што је веома ретко и што може довести до додатних проблема.

АКо треба радити са променљивом чија се вредност неће мењати током њеног животног циклуса, препоручује се да се таква променљива декларише коришћењем резервисане речи const.

Пример. Ислуструје коришћење кључних речи за декларисање променљивих и одговарајуће опсеге њихове дефинисаности:

const osoba1 = "Никола";
console.log(osoba1)

let osoba2 = osoba1 + "!!!!"
console.log(osoba2)

// nemoguce - pokusaj postavljanja 
// vrednosti za konstantnu promenljivu
osoba1 = "Драгослав"

// rad sa promenljivom deklarisanom
// pomocu var
{
    var osoba3 = "Петар"
    console.log(osoba3)
}
console.log(osoba3 + " " + osoba2)

// rad sa promenljivom deklarisanom
// pomocu let
{
    let osoba4 = "Јован"
    console.log(osoba4)
}
// nemoguce - pokusaj pristupa
// promenljvoj van njenog opsega
// definisanosti
console.log(оsoba4 + " " + osoba2)

Пример. Ислуструје коришћење глобалних променљивих и препоруке да се користи стриктни мод:

'use strict'
osoba2 = "Никола"
console.log(osoba2)

Наравно, јасно је да коришћење глобалних променљивих трба да се максимално избегава.

Треба напоменути да опсег није исто што и окружење тј. контекст. Ова два појма се јер имају неке сличности али треба знати да је појам опсег је особина промењиве, док је контекст особина програмског кŏда.

Када се програм покрене, окружење није празно - оно већ садржи променљиве које су део језичког стандарда, као и променљиве које обезбеђују начин интеракције програма са системом који га окружује. Током извршавања, програм пролази (улази и излази) кроз различите опсеге промењиве, а промењиве су тада или у контексту или ван њега.

Контекст је сличан опсегу јер такође зависи од позиције у програму (лексички контекст) или времена извршавања кода (контекст извршавања).

Опсези и контексти ће бити додатно описани приликом описивања функција у ЈаваСкрипту.

Изрази

Изрази су делови програмског кŏда који могу бити евалуирани и чија се вредност може израчунати.

Иако сваки синтаксно коректан израз приликом евалуације добије неки вредност, у принципу се разлику два типа израза:

  1. изрази са бочним ефектима (нпр. израз којим се променљивој додељује вредност) и

  2. изрази су без бочног ефекта.

Пример. Конретан пример за први тип израза је x = 7 - у том случају се користи оператор доделе вредности = да би се вредност седам доделила променљивој x. У том случају, целокупном изразу ће приликом евалуације бити додељена бројчана вредност седам.

Конкретан пример за други тип израза је 3 + 4 - у том случају се користи оператор + како би се сабрали тројка и четворка и добила вредност седам, али тај резултат не бива додљен променљивој. █

Постоје различите категорије израза:

Примарни изрази

У примарне изразе спадају претходно описани литерали и константе, као и променљиве, које су описане у поглављу.

У примарне изразе спадају и следеће кључне речи језика ЈаваСкрипт:

Аритметички изрази

У ову категорију спадају сви изрази који се евалуирају у бројеве.

При грађењу аритметичких израза, користе се аритметички оператори и функције које враћају бројеве.

Аритметички оператори се користе за означавање аритметичких операција. Ови оператори имају већи приоритет од оператори поређења, који имају већи приоритет од логичких оператора.

Оператор Опис
+ унарни плус и сабирање
- унарни минус и одузимање
* множење
/ дељење
% модуо
++ инкрементирање
-- декрементирање
** степен

Као што је већ истакнуто при опису омотавања, бројеви се може посматрати као Number објекат.

У том случају на број могу да се примене следеће методе:

Поред уграђених метода за рад са бројевима, постоје и методи за реализацију математичких функција, за рад са нискама, за рад са низовима и сл. који враћају бројчане вредности - позиви таквих метода се такође могу наћи у оквиру аритметичких израза.

Пример. Илуструје извршавање операција над бројевима приликом евалуације аритметичких израза.

// operatori i operandi
console.log(100 + 4 * 11);

// zagrade utiču na prioritet
console.log((100 + 4) * 11);

// operatori istog prioriteta se izvršavaju sdesna ulevo
console.log(1 - 2 + 1);

// operator za računanje ostatka pri deljenju
console.log(314 % 100);

// specijalna vrednost +beskonačno
console.log(Infinity);

// dobijanje specijalne vrednosti +beskonačno
console.log(47 / 0);

// specijalna vrednost -beskonačno
console.log(-Infinity);

// dobijanje specijalne vrednosti -beskonačno
console.log((47 - 50) / (500 - 500));

// specijalna vrednost NaN
console.log(NaN);

// dobijanje specijalne vrednosti NaN
console.log((47 / 47 - 1) / (500 - 500));

// dobijanje specijalne vrednosti NaN
console.log((47 / 0) - (500 / 0));

// dobijanje specijalne vrednosti NaN
console.log((47 / 0) / (500 / 0));

Битовски изрази су у ствари аритметички изрази, који се добијају када се битовски оператори примене на целобројне аргументе. Битовски оператори се користе за рад са низом појединачних битова (1 и 0), који су “спаковани” у једну вредност.

Битовски оператори су:

Унарни оператор ~ има највећи приоритет и он је десно асоцијативан. Међу бинарним битовским операторима највећи приоритет има оператор померања,након тога следи & који има већи приоритет од ^, који опет има већи приоритет од |. Битовни бинарни оператори су лево асоцијативни.

Пример. Илуструје рад са битовним операторима.

let x = 5 & 1; // 5&1=(0101)&(0001)=(0001) pa je razultat 1
 x = 5 | 1;   // 5|1=(0101)|(0001)=(0101) pa je razultat 5
 x = ~ 5; // 5=0101 bitovski ~5=1010 sto je 10
 x = 5 ^ 1;  // (0101)^(0001)=(0100) pa je rezultat 4
 x = 5 << 1; // 5=0101 a kada 5 siftujemo za jedan ulevo dobijamo 1010 sto je 10
 x = 5 >> 1; // 5=0101 a kada 5 siftujemo za jedan udesno dobijamo 0010 sto je 2

Логички изрази

Логички изрази приликом евалуације враћају вредности логичког типа (true или false).

Над логичким вредностима се могу применити логички оператори. Постоје следећи логички оператори:

У логичким изразима могу учествати оператори који враћају логичку вредност. Такви оператори су нпр. оператори поређења, који упоређују вредности два израза, тј. вредност израза лево од оператора поређења пореде са вредношћу израза десно од оператора поређења.

Симбол Значење
== враћа вредност true ако су вредности једнаке, тј. исте (нпр. x == y)
=== враћа вредност true ако су вредности идентичне, тј. једнаке и ако су истог типа (нпр. x === y)
!= враћа вредност true ако су вредности нису једнаке (нпр. x != y)
!== враћа вредност true ако су вредности нису идентичне (нпр. x !== y)
> враћа вредност true ако је вредност с леве стране већа од вредности с десне стране (нпр. x > y)
< враћа вредност true ако је вредност с леве стране мања од вредности с десне стране (нпр. x < y)
>= враћа вредност true ако је вредност с леве стране већа или једнака од вредности с десне стране (нпр. x >= y)
<= враћа вредност true ако је вредност с леве стране мања или једнака од вредности с десне стране (нпр. x <= y)

Са логичким изразима је уско везан и оператор условног израза, који испитује да ли је услов испуњен (при евалуацији услова добија се вредност true), па ако јесте резултат је вредност израза између упитника и двотачке, а ако није резултат је вредност након двотачке.

Пример. Илуструје рад са логичким изразима.

// zapis vrednosti true
console.log(true);

// zapis vrednosti false
console.log(false);

// poređenje brojeva
console.log(33 > 5.5);

// poređenje brojeva
console.log(33 < 5.5);

// poređenje niski
console.log("Ananas" > 'Banana');

// poređenje niski
console.log('33' < '5.5');

// poređenje niski
console.log('auto' < 'automobil');

// poređenje niski
console.log('auto' < 'Automobil');

// poređenje specijalnih brojeva
console.log(-Infinity < -100e40);

// poređenje specijalnih brojeva
console.log(-Infinity == -Infinity);

// poređenje specijalnih brojeva
console.log(NaN == NaN);

// operator i
console.log(true && false);

// operator i
console.log(true && true);

// operator ili
console.log(false || false);

// operator ili
console.log(false || true);

// prioritet operacija
console.log(1 + 1 == 2 && 10 * 10 > 50);

// operator uslovnog izraza
console.log(true ? "prvi" : "drugi");

// operator uslovnog izraza
console.log(false ? 1 : "drugi");

Ниска-изрази

Ниска-изрази приликом евалуације враћају вредности знаковних ниски.

Приликом креирања нових ниски, често се користи оператор спајања +.

Као што је већ истакнуто при опису омотавања, ниска се може посматрати као String објекат.

У том случају на ниску могу да се примене методе дате следећом табелом:

Назив методе Опис
charAt() враће знак на датој позицији
charCodeAt() враће Unicode вредност за знак на датој позицији
concat() враће спој две ниске
fromCharCode(code) претвара Unicode вредност code у одговарајући знак
indexOf() враће позицију прве пронађене појаве дате вредности у ниски
lastIndexOf() враће позицију последње пронађене појаве дате вредности у ниски
localeCompare() пореди две ниске, узимајући у обзир актуелну локацију
match() претражује ниску ради уклапања регуларног израза и враће нађено уклапање
replace() претражује ниску ради налажења вредности или уклапања регуларног израза и враће ниску у којој су извршене замене
search() претражује ниску ради налажења вредности или уклапања регуларног израза и враће позицију нађеног уклапања
slice() враће издвојени део ниске
split() враће низ подниски оригиналне ниске, зависно од прослеђеног сепаратора
substr() враће подниску ниске дате дужине, почев од почетне позиције
substring() враће подниску ниске између два дата индекса
toLocaleLowerCase() враће ниску претворену у мала слова, узимајући у обзир актуелну локацију
toLocaleUpperCase() враће ниску претворену у велика слова, узимајући у обзир актуелну локацију
toLowerCase() враће ниску претворениу у мала слова
toString() враће вредност одговарајућег String објекта омотача
toUpperCase() враће ниску претворену у велика слова
trim() враће ниску у којој су уклоњене белине са почетка и са краја
valueOf() враће ниска-вредност, тј. вредност примитиве
Шаблони за ниске

Шаблони за ниске, уведени у верзији ЈаваСкрипта ES6 (та верзија се означава и са ES2015), су ниска-литерали који допуштају моћнији начин за дефинисање ниски.

Шаблони за ниске су, уместо апострофа или наводаника, ограничени обрнутим апостофом (тј. знаком `). У оквиру шаблона за ниске се могу налази места за замену, која су означена тако што су обухваћена витичастим заградама испред којигх се налази знак за долар, нпр. ${izraz}. У претходном примеру, izraz се налази унутар места за замену и он се прослеђује функцији, која врши спајање делова у једну ниску. Функција ће пре спајања у ниску извршити евалуцаију израза у оквиру места за замену и добијене резултате спојити у резултујућу ниску.

Код шаблона за ниске, белине (знаци за крај линије, размаци, табови и сл.) не треба да се представљају промоћу ескејп-знакова, већ се могу директно унети у шаблон. Начин формирања ниски преко шаблона је елегантнији од “класичног” спајања ниски оператором + и продукује читљивији програмски код.

Пример. Рад са оператором спајања и са шаблонима за ниске:

// spajanje niski
console.log('Tri plus sest je ' + (3 + 6) + '.');
// "Tri plus sest je 9."

// sabloni za niske
console.log(`Tri plus sest je ${3 + 6}.`);
// "Tri plus sest je 9."

// spajanje niski
console.log("Draga mama,\n" +
"Nadam se da si dobro.\n" +
"\tPozdrav, tvoj sin")

// sabloni za niske
console.log(`Draga mama,
Nadam se da si dobro.
    Pozdrav, tvoj sin`);

Ако се појави потреба да се у оквиру шаблона за ниску појави обрнути апостоф, то се може постићи помоћу одговарајуће ескејп-секвенце, тј. знака `.

Изрази леве стране

Ови изрази представљају одредиште наредбе доделе (било директно, било имплицитно). То могу бити:

Вредности се изразима леве стране додељују се коришћењем оператора доделе. Најчешћи оператор додељивања је знак једнакост =. Оператор доделе може се писати заједно са бинарним аритметичким операторима, као у табели која следи:

Симбол Значење
= додељује вредност променљиве или израза с десне стране променљивој или изразу леве стране (нпр. x=y)
+= сабира изразе са леве и десне стране и додељује збир променљивој или изразу леве стране (нпр. x = x + y)
-= одузима изразе са леве и десне стране и додељује разлику променљивој или изразу леве стране (нпр. x = x - y)
*= множи изразе са леве и десне стране и додељује производ променљивој или изразу леве стране (нпр. x = x * y)
/= дели изразе са леве стране изразом са десне стране и додељује количник променљивој или изразу леве стране (нпр. x = x / y)
%= рачуна остаак при дељењу израза са леве стране изразом са десне стране и додељује остатак изразу леве стране (нпр. x = x % y)

Приоритет оператора

Под операторима се најчешће подразумева симболи који се користе када треба извршити неку стандардну често коришћену операцију као нпр. додела вредности, поредјење вредности, аритметичке операције и сл.

Приоритет оператора одређује којим ће се редом оперантори примењивати, а асоцијативност оператораодређује са ког краја се одвија груписање операнада (почев од левог или од десног краја). Сваки оператор има свој ниво приоритета и своје правило асоцијативности.

У наредној табели су приказани оператори и њихова асоцијативност. Редослед оператора у табели је дат по њиховом приоритету - од оних са највишим приоритетом извршавања наниже:

Приоритет Ознака Назив Асоцијативност
20 ( … ) заграде за груписање н/д
19 . приступ особини објекта тачка-нотацијом слева удесно
… [ … ] приступ особини објекта нотацијом угластих заграда слева удесно
new … ( … ) оператор new (са аргументима) н/д
18 … ( … ) позив функције слева удесно
new … оператор new (без аргумената) сдесна улево
17 … ++ постфиксно увећавање н/д
… — постфиксно умањивање н/д
16 ! … логичка негација сдесна улево
~ … битовна негација сдесна улево
+ … унарни плус сдесна улево
– … унарни минус сдесна улево
++ … префиксно увећање сдесна улево
— … префиксно умањење сдесна улево
typeof … оператор typeof сдесна улево
void … оператор void сдесна улево
delete … оператор delete сдесна улево
15 … ** … степеновање сдесна улево
14 … * … множење слева удесно
… / … дељење слева удесно
… % … остатак при дељењу слева удесно
13 … + … сабирање слева удесно
… – … одузимање слева удесно
12 … << … битовно померање улево слева удесно
… >> … битовно померање удесно слева удесно
… >>> … битовно неозначено померање удесно слева удесно
11 … < … мањи слева удесно
… <= … мањи или једнак слева удесно
… > … већи слева удесно
… >= … већи или једнак слева удесно
… in … оператор in слева удесно
… instanceof … оператор instanceof слева удесно
10 … == … једнакост слева удесно
… != … различитост слева удесно
… === … идентичност слева удесно
… !== … неидентичност слева удесно
9 … & … битовна конјукција слева удесно
8 … ^ … битовна ексклузивна дисјункција слева удесно
7 … | … битовна дисјункција слева удесно
6 … && … логичка конјукција слева удесно
5 … || … логичка дисјункција слева удесно
4 … ? … : … условни израз сдесна улево
3 … = … додела сдесна улево
… += …
… -= …
… **= …
… *= …
… /= …
… %= …
… <<= …
… >>= …
… >>>= …
… &= …
… ^= …
… |= …
2 yield … оператор yield сдесна улево
yield* … оператор yield* сдесна улево
1  … проширење н/д
0 … , … зарез/секвенца слева удесно

Пример. Коришћење унарних и бинарних оператора:

// operator typeof primenjen na broj
console.log(typeof 4.5);
// Prikazaće: number

// operator typeof primenjen na broj
console.log(typeof 4);
// Prikazaće: number

// operator typeof primenjen na nisku
console.log(typeof " x ");
// Prikazaće: string

// operator promene znaka
console.log(-(10 - 2));
// Prikazaće: -8

Конверзија типова и евалуација израза

ЈаваСкрипт је слабо типизиран језик, што значи да не захтева да се јасно декларише тип при декларисању промењиве. Код ЈаваСкрипта се тип промењиве имплицитно декларише са придруживањем одређене вредности датој промењивој.

ЈаваСкрипт је такође језик динамичких типова јер је могућа промена типа у току извршења програма. Резултат конверзије је увек нека примитивна вредност, тј. не постоји конверзија чији је резултат нека сложена вредност (као што је објекат или функција).

Експлицитна конверзија типа

Када треба променити тип података неке промењиве то се зове експлицитна конверзија типова и врши се користећи неку од уграђених функција за конверзију:

Имплицитна конверзија типа

Имплицитна конверзија типова се односи на конверзије које нису експлицитне а извршава их ЈаваСкрипт извршно окружење у ходу као споредни ефекат неких других радњи. Имплицитна конверзија се најчешће јавља када се вредност неког типа користи на начин који аутоматски проузрокује њену конверзију.

Следи табела имплицитних конверзија:

Оригинална
вредност
Конверзија у
Number
Конверзија у
String
Конверзија у
Boolean
false 0 “false” false
true 1 “true” true
0 0 “0” false
1 1 “1” true
“0” 0 “0” true
“000” 0 “000” true
“1” 1 “1” true
NaN NaN “NaN” false
Infinity Infinity “Infinity” true
-Infinity -Infinity “-Infinity” true
“” 0 “” false
“20” 20 “20” true
“twenty” NaN “twenty” true
[] 0 “” true
[20] 20 “20” true
[10,20] NaN “10,20” true
[“twenty”] NaN “twenty” true
[“ten”,”twenty”] NaN “ten,twenty” true
function(){} NaN “function(){}” true
{} NaN “[object Object]” true
null 0 “null” false
undefined NaN “undefined” false

Најчешће су разлози за имплицитну конверзију поређење или нека друга математичка операција између различитих типова промењивих. Поред овога имплицитна конверзија се дешава и услед потребе за израчунавањем неког услова.

Поређење помоћу оператора ==

Један од најпознатијих примера имплицитне конверзије је “поређење прама једнакости”, након чега се добија логичка вредност. Алгоритам за одређивање логичке вредности која представља резултат поређења тј. x == y је следећи:

  1. Ако су x и y истог типа, тада се извршава стриктно поређење ===

  2. Ако је промењива x null или undefined, тада се враћа true

  3. Ако је промењива x undefined а промењива y null, тада се враћа true

  4. Ако је промењива x Number а промењива y String, онда враћа резултат поређења x === ТоNumber(y)

  5. Ако је промењива x String а промењива y Number, онда враћа резултат поређења ТоNumber(x) === y

  6. Ако је промењива x Boolean а промењива y Number, онда враћа резултат поређења ТоNumber(x) === y

  7. Ако је промењива x Number а промењива y Boolean, онда враћа резултат поређења x === ТоNumber(y)

  8. Ако је промењива x Number или String или Symbol а промењива y Object, онда враћа резултат поређења x == ToPrimitive(y)

  9. Ако је промењива x Object а промењива y Number или String или Symbol, онда враћа резултат поређења ToPrimitive(x) == y

  10. Ако није ништа од претходно наведеног, тада се враћа False

У следећој табели су уписани сви случајеви између свих могућих типова за поређење оператором ==:

  Operand B
    Undefined Null Number String Boolean Object
Operand A Undefined true true false false false false
Null true true false false false false
Number false false A === B A === ToNumber(B) A === ToNumber(B) A == ToPrimitive(B)
String false false ToNumber(A) === B A === B ToNumber(A) === ToNumber(B) A == ToPrimitive(B)
Boolean false false ToNumber(A) === B ToNumber(A) === ToNumber(B) A === B ToNumber(A) == ToPrimitive(B)
Object false false ToPrimitive(A) == B ToPrimitive(A) == B ToPrimitive(A) == ToNumber(B) A === B

Пример. Илуструје како се извршава евалуација израза уз имлицитну конверзију типова.

/* automatska konveryija tipova pri izvršenju aritmetičkih operacija */
console.log(8 * null);
// prikazaće 0

console.log("5" - 1);
// prikazaće 4

console.log("5" + 1);
// prikazaće 51

console.log("pet" * 2);
// prikazaće NaN

/* automatska konverzija tipova pri izvršenju operacija poređenja */
console.log(false == 0);
// prikazaće true

/* poređenje jednakosti za vrednosti null i/ili undefined se
   realizuje na pomalo specifičan način  */
console.log(null == undefined);
// prikazaće true

console.log(null == 0);
// prikazaće false

/* logički operatori se "skraćeno" izvršavaju */
console.log(undefined || "Karlo");
// prikazaće Karlo

console.log("Karlo" || "Korisnik");
// prikazaće Karlo

Примери за типове вредности и изразе

Наредбе и секвенце наредби

Сви претходно описани изрази већ сами по себи представљају наредбе програмског језика ЈаваСкрипт. Наравно, програми написани на овакав начин би имали мало смисла.

Извршавање ЈаваСкрипт програма тј. скрипте почиње тако што се изврши прва нардба у скрипти, затим друга, и тако редом… Секвенијално извршавање наредби се може изменити коришћењем наредби гранања и цикулуса, као што је то случај и у програмском језику C.

Пример. Секвенца наредби са мало смисла:

// primer naredbe
6*7;

// jos jedan primer naredbe
7*6

// primer beskorisnog programa
1;
! false;

// jos jedan primer beskorisnog programa
1
! false

Следећа секвенца представља смисленији програм.

// sekvencijalno izvršavanje
let br = Number("23");
br = br - 10
console.log (br + " je kvadratni koren broja " + br * br);

За разлику од програмског језика C, где се наредба обавезно морала завршити са знаком тачка-зарез (енг. semicolumn тј. ;), ЈаваСкрипт наредба се може завшити или знаком тачка-зарез или знаком за крај реда. Другим речима, код језика ЈаваСкрипт у новом реду почиње нова наредба, осим ако се текући ред на завршава обратном косом цртом (енгл. backslash тј. \) или ако се не ради о шаблону за ниске који се простире кроз више редова.

Наредбе доделе вредности

У овој наредби фигурише оператор доделе =. Наредбa доделе је истовремено и израз, са бочним ефектом. Евалуација наредбе доделе се врши тако што се израчунава вредност израза који се налази десно од знака =, та израчуната вредност се додељује левом изразу (то може бити променљива, особина објекта, елеменат низа и сл.) који се налази лево од знака = и коначан резулата евалуцаије је израчуната вредност израза на десној страни.

Комбиноване наредбе доделе

Комбиноване наредбе доделе представљају комбинацију операције и наредбе доделе. Оператори код комбиновани наредби дoделе су: +=, -=, *=, /=, %=, <<=, >>=, >>>=, &=, ^=, |= и **=.

Пример. Комбинована наредба доделе x += y је еквивалентна наредби доделе x = x + y. █

Наредбе инкрементирања и декрементирања

Наредбе инкрементирања и декрементирања сажимају најкоришћеније комбиноване наредбе доделе. Оне користе операторе увећања за један (инкрементирања) ++ и оператор умањења за један (декрементирања)--.

Пример. Наредба инкрементирања x++ је еквивалентна комбинованој наредби доделе x += 1. █

Оператори инкрементирања и декрементирања могу бити префиксни или постфиксни. Ако је оператор инкрементирања/декрементирања префиксан, онда се приликом евалуације израза у којој учествује овај оператор, инкрементирање/декрементирање извршава на почетку, а ако је оператор постфиксан, инкрементирање/декрементирање ће се извршити на крају евалуирања израза.

Позиви предефинисаних функција

Као што је случај и у другим “мејнстрим” програмским језицима, и код ЈаваСкрипта изрази у нарадбама могу садржати позиве функција. Неке од често коришћених функција су предефинисане, тј. садржане су у оквиру ЈаваСкрипт језика и одмах су на располагању програмеру.

У склопу самог ЈаваСкрипта постоје уграђени објекти са својим својствима и методама, намењени да олакшају програмирање. Дакле, програмер може одмах користити те објкете, њихове особине особине и методе - тј. предефинисане објекте и предефинисане функције. ЈаваСкрипт сасдржи следеће предефинисане објекте:

Структура предефинисаних објеката Array, Date и Function ће бити описана у секцијама које се баве низовима, радом са датумима и функцијама.

Поред горе наведених, постоје још и објекти чија имена су иста као имена простих примитива, само са великим почетним словом:

Ови омотачи су, како је претходно описано, уведени како би се ЈаваСкрипт програмеру олакшао рад са примитивном подацима. Методе које су програмеру на располагању за String и за Number су претходно описане.

Објекат Math

Објекат Math садржи особине, чијим се реферисањем добијају неке од познатих математичких константи:

Особина објекта Опис
E Враће Ојлерову константу (прибл. 2.718)
LN2 Враће логаритам од 2 за основу е (прибл. 0.693)
LN10 Враће логаритам од 10 за основу е (прибл. 2.302)
LOG2E Враће логаритам од е за основу2 (прибл. 1.442)
LOG10E Враће логаритам од 10 за основу е (прибл. 0.434)
PI Враће PI (прибл. 3.14)
SQRT1_2 Враће квадратни корен од 1/2 (прибл. 0.707)
SQRT2 Враће квадратни корен од 2 (прибл. 1.414)

Методе Math објекта узимају број/бројеве као argument а враћају резултат математичке функције извршене над тим бројем/бројевима:

Метода објекта Опис
abs(x) Враће апсолутну вредност x
acos(x) Враће аркус косинус x, у радијанима
asin(x) Враће аркус синус x, у радијанима
atan(x) Враће аркус тангес x као број између -PI/2 и PI/2 радијана
atan2(y,x) Враће аркус тангес количника аргумената, тј. y/x
ceil(x) Враће x, заокружено на већи цео број
cos(x) Враће косинус x (x је у радијанима)
exp(x) Враће вредност експоненцијалне функције, тј. еx
floor(x) Враће x, заокружено на мањи цео број
log(x) Враће логатирам од x за осонову е
max(x,y,z,…,n) Враће масималну вреднсот аргумената
min(x,y,z,…,n) Враће минималну вреднсот аргумената
pow(x,y) Враће вредност степене функције, тј. x y
random() Враће псеудослучајни број између 0 и 1
round(x) Враћеx заокружено на најближи цео број
sin(x) Враће синус x (x је у радијанима)
sqrt(x) Враће квадратни корен x
tan(x) Враће тангес x (x је у радијанима)

Пример. Позиви математичких функција:

// pozivaju se funkcije Math.max i console.log
console.log(Math.max(2, 4));
console.log(Math.max(2, 4, 7, 6));
let miki = -5;
console.log(Math.min(2, 4, 7, 6, miki, Math.PI));

Пример. Секвенца наредби којом се генеришу и приказују псеудо-случајни бројеви:

// pozivaju se funkcije Math.random i console.log
let x = 6 * Math.random()-3
console.log(x);
x = 6 * Math.random()-3
console.log(x);
x = 6 * Math.random()-3
console.log(x);
x = 6 * Math.random()-3
console.log(x);

Објекат Console

Oвај објекат обезбеђује приступ било конзоли за дебагирање код прегледача, било конзоли за приказ код node.js. Конкретни начин рада конзоле се разликује од једне до друге платформе, али увек постоји скуп функционалности које су обезбеђене - фактички је стандардизована функционалност конзоле.

Објекту Console се може приступити из ма ког глобалног објекта - код прегледача је изложена као Window.console и на њу се може једностано реферисати са console.

Пример. Позиви функцијa за приказ на конзолу:

let x = 20;

// poziva se funkcija console.log
console.log("vrednost poromenljive x je", x);

// poziva se funkcija console.log, uz spajanje niski
console.log("vrednost poromenljive x je " + x);

// poziva se funkcija console.log, uz sablon za nisku
console.log(`vrednost poromenljive x je ${x}`);

Гранања

Наредбама гранања се доноси одлука којим ће се од више алтернативних токова наставити извршавање. Одлука се доноси на основу вредности датог израза.

Наредба if

Наредба if има исту структуру и начин извршавања као у програмском језику C.

Пример. Коришћење просте наредбе условног гранања if:

// uslovno izvršavanje
let br = 10 * Math.random()  - 5
console.log ( `Pseudo-slucajni broj ima vrednost ${br}` )
if (br > 0 )
    console.log (`Pseudo-slucajni broj je pozitivan`);

Пример. Коришћење наредбе условног гранања ifсаelse граном:

// uslovno izvršavanje
let br = 10 * Math.random()  - 5;
console.log ( `Pseudo-slucajni broj ima vrednost ${br}` );
if (br > 0 )
    console.log (`Pseudo-slucajni broj je pozitivan`);
else
    console.log (`Pseudo-slucajni broj je negativan`);

Пример. Коришћење угњеждена наредбе if-else:

// ugnјeždena if naredba
let br = 10 * Math.random() - 5;
console.log(`Псеудо-случајни број има вредност ${br}`);
if (br <= 0)
    console.log(`Број је негативан`);
else if (br == 0)
    console.log(`Број је тачно 0`);
else if (br < 2)
    console.log(`Број је позитиван, мањи од 2`);
else
    console.log(`Број је већи или једнак од 2`);

Наредба switch

Наредба вишеструког гранања switch има исту структуру и начин извршавања као што је то случај у програмском језику C.

Пример. Коришћење наредбе switch-case:

// visestruko grananje koriscenjem naredbe switch
let godisnjeDoba = Math.floor( (Math.random() * 40) % 5 );
switch (godisnjeDoba) {
    case 0:
        console.log("Ponesite kišobran.");
        break;
    case 1:
        console.log("Ponesite naočari za sunce.");
    case 2:
        console.log(`Ponesite rukavice.`);
    case 3:
        console.log("Obucite patike za šetnju.");
        break;
    default:
        console.log("Ovo je neko nemoguće doba...");
        break; 
}
console.log( `Vrednost indikatora je ${godisnjeDoba}` );

Циклуси

Често се јавља потреба да се унутар програма неке наредбе извршавају више пута. Овај начин извршавања се остварају помоћу одговарајућих управљачких структура. Циклуси (бројачки и колекцијски) су основни градивни елемент сваког програма. Бројачки циклуси се јављају мање-више у истом облику у скоро свим програмским језицима, а колекцијски се ослањају на пролазак тј. итерирање кроз колекцију (нпр. кроз елементе низа или кроз особине објекта).

У овом поглављу ће се описати само бројачки циклуси, а колекцијски ће бити описнане у посебномј секцији, после описа низова, објеката и функција.

Опсези важења променљивих у циклусима

Опсег важења променљиве је блоковски, ако је променљива декларисана коришћењем let. Ово важи и за пројачке променљиве које се декларишу у иницјалној секцији for циклуса. Тако декларисаним променљиваима се може само приступити у коду унутар циклуса - извршавање наредби ван циклуса којима се покушава приступити таквим променљивима доводи до грешке.

Са друге стране, ако је променљива у телу циклуса или у иницијализационој секцији for циклуса декларисана коришћењем наредбе var, онда се тој промељивој може приступити и у наредбама које се налазе ван циклуса.

Циклус while

Наредба циклуса са предусловом while има исту структуру и начин извршавања као у програмском језику C.

Пример. Коришћење наредбе while за рачунање 2 степеновано на 10:

let res = 1;
let brojac = 0;
while (brojac < 10) {
    res = res * 2;
    brojac = brojac + 1;
}
console.log(res);

Пример. Коришћење наредбе while за рачунање 2 степеновано на 10, коришћењем наредби сажетог ажурирања:

let res = 1;
let brojac = 0;
while (brojac < 10) {
    res *= 2;
    brojac++;
}
console.log(res);

Циклус do while

Наредба циклуса са постусловом do-while има исту структуру и начин извршавања као што је то случај у програмском језику C.

Пример. Скрипта која, коришћењем наредбе do-while, генерише случајан број све док генерисани број није негативан:

let pokusaja = 0;
do {
    var slucajan = Math.random() - 0.1;
    pokusaja = pokusaja + 1;
} while (slucajan >= 0);
console.log(`Извучен је негативан случајан број ${slucajan} из \
    покушаја бр. ${pokusaja}`);

Циклус for

Наредба бројачког циклуса for има исту структуру и начин извршавања као што је то случај у програмском језику C. Поред бројачког for циклуса, језик ЈаваСкрипт садржи и колекцијек циклусе for-in (итерира кроз индексе којима се приступа елементима колекције) и for-of (итерира кроз саме елементе колекције).

Пример. Скрипта која, коришћењем наредбе for, рачуна 2 на десети степен:

let res = 2;
for (let brojac = 1; true; brojac++) {
    if (brojac % 10 == 0)
        break;
    res *= 2;
}
console.log(res);

Пример. Скрипта која, коришћењем наредбе for понавља извлачење псеудослучајних бројева док извучени број не буде између 0 и 0.1, а потом приказује извучени број, као ито из ког је покушаја тај број извучен:

let slucajan = Math.random();
console.log(slucajan);
for(var pokusaja = 1; slucajan >= 0.1; pokusaja++){
    slucajan = Math.random();
    console.log(slucajan);
}
console.log(`Извучен је случајан број ${slucajan} мањи од 0.1 из \
    покушаја бр. ${pokusaja}`);

Пример. Скрипта која, коришћењем наредбе for (циклус у циклусу) 20 пута понавља серију извлачења псеудослучајних бројева док извучени број не буде између 0 и 0.1, приказује извучени псеудослучајн број, број елементата у серији, као и просечну дужину серије:

const n = 20
let prosecnoPokusaja = 0
for (let i = 0; i < n; i++) {
    var slucajan = Math.random();
    for (var pokusaja = 1; slucajan >= 0.1; pokusaja++) {
        slucajan = Math.random();
    }
    console.log(`Извучен је случајан број ${slucajan} мањи од 0.1 из \
        покушаја бр. ${pokusaja}`);
    prosecnoPokusaja += pokusaja
}
console.log(`Просечан број покушаја је ${prosecnoPokusaja/n}`);

Искакање из циклуса и прескакње итерације

Искскање из циклуса значи да у језику ЈаваСкрипт постоји механизам који допушта да се извршењем наредбе у телу циклуса, не консулујући услов за циклус, изврши искакање и прелазак на следећу наредбу ван тог циклуса, или на следећу наредбу ван обележеног циклуса који обухвата тај циклус.

Прескакање итерације циклуса значи да у језику ЈаваСкрипт постоји механизам који допушта да се извршењем наредбе у телу циклуса изврши прескакање преосталих наредби у телу циклуса и прелазак на следећу итерацију циклуса, или прелазак на следећу итерацију обележеног циклуса који обухвата тај циклус.

Искакање из циклуса

Исто као у програмском језику C, искакање из циклуса се постиже нареднбом break. Наредба break, исто као у програмском језику C, може бити без обележја или са обележјем.

Пример. Скрипта са бесконачним for циклусом са искакањем (без обележја), за рачунање 2 на десети степен:

let res = 2;
for (let brojac = 1; true; brojac++) {
    if (brojac % 10 == 0)
        break;
    res *= 2;
}
console.log(res);

Пример. Скрипта са бесконачним for циклусом са искакањем (без обележја), којом се понавља извлачење псеудослучајних бројева док извучени број не буде између 0 и 0.1, а потом приказује извучени број, као ито из ког је покушаја тај број извучен:

var slucajan = Math.random();
for(var pokusaja = 1; ; pokusaja++){
    console.log(slucajan);
    if( slucajan < 0.1)
      break;
    slucajan = Math.random();
}
console.log(`Извучен је случајан број ${slucajan} мањи од 0.1 \
    из покушаја бр. ${pokusaja}`);

Прескакање итерације циклуса

Исто као у програмском језику C, прескакње итерације се постиже наредбомcontinue. Нредба continue може бити са или без обележја.

Пример. Скрипта која, коришћењем необележеног прескакње итерације, пребројава колико се пута случајан број нашао између 0 и 0.1 (што представља успех експеримента). При томе, експерименти се понацљају по 100 пута у серији, број серија је 20, а без обзира на неуспех/успех експеримента, експерименти ће бити настављени у текућој серији:

const brojSerija = 20
const brojPonavljanjaUSeriji = 100
let uspesnihPokusaja = 0
centralna:
for (let i = 0; i < brojSerija; i++) {
  for(let j=0; j<brojPonavljanjaUSeriji; j++){
    let slucajan = Math.random();
    if( slucajan >= 0.1)
      continue;
    uspesnihPokusaja++;
  }
}
console.log(`Укупан број серија је ${brojSerija}`);
console.log(`Број понављања у серији је ${brojPonavljanjaUSeriji}`);
console.log(`Број успешних покушаја је ${uspesnihPokusaja}`);

Обележено искакање иа циклуса и обележено прескакање итерације

Исто као у програмском језику C и Јави, постоји могућност да се одређеном циклусу додели обележје (енгл. label), па да се потом искакње или прескакање итерације односе на тај обележни циклус, а не на најунутрашњији блок (какав је случај код верзије наредби искакања и прескакања итерације које не садрже обележја).

Пример. Скрипта која, коришћењем необележеног искакaња из циклуса, пребројава колико je укупно било покушаја пре успеха, тј. пре него што се случајан број нашао између 0 и 0.1 у 20 серија понављања експеримента. При томе, у свакој серији експеримент се понављао све док не дође до успеха, који доводи до прекида текуће и почетка нове серије:

const brojSerija = 20;
let ukupnoPokusaja = 0;
for (let i = 0; i < brojSerija; i++) {
  for (var pokusaja = 0; ; pokusaja++) {
    let slucajan = Math.random();
    if (slucajan < 0.1)
      break;
  }
  ukupnoPokusaja += pokusaja;
}
console.log(`Укупан број покушаја је ${ukupnoPokusaja}`);

Пример. Скрипта која, коришћењем обележеног искакaња из циклуса, пребројава колико je укупно било покушаја пре успеха, тј. пре него што се случајан број нашао између 0 и 0.1 у 20 серија понављања експеримента. При томе, у свакој серији експеримент се понављао све док не дође до успеха, који доводи до прекида свог даљег рада:

const brojSerija = 20
let ukupnoPokusaja = 0
centralna:
for (let i = 0; i < brojSerija; i++) {
  for (; ;) {
    let slucajan = Math.random();
    ukupnoPokusaja++;
    if (slucajan < 0.1)
      break centralna;
  }
}
console.log(`Укупан број покушаја је ${ukupnoPokusaja}`);

Пример. Скрипта која, коришћењем обележеног прескакања итерација, пребројава колико je укупно било покушаја пре успеха, тј. пре него што се случајан број нашао између 0 и 0.1 у 20 серија понављања експеримента. При томе, у свакој серији експеримент се понављао све док не дође до успеха, који доводи до прекида текуће и почетка нове серије:

const brjSerija = 20;
let ukupnoPokusaja = 0;
centralna:
for (let i = 0; i < brjSerija; i++) {
  for (let j = 0; j < 100; j++) {
    let slucajan = Math.random();
    ukupnoPokusaja++;
    if (slucajan < 0.1)
      continue centralna;
  }
}
console.log(`Укупан број покушаја је ${ukupnoPokusaja}`);

Литература

  1. Haverbeke M.: Eloquent JavaScript

  2. Симпсон К.: You Don’t Know JS: Types & Grammar

  3. Симпсон К.: You Don’t Know JS: Scope & Closures

  4. JavaScript - Mozzila Developer Network (MDN)

  5. Живановић, Д.: Веб програмирање - ЈаваСкрипт

  6. Copes F.: Complete JavaScript Handbook