JavaScript tipovi podataka

JavaScript spada u slabo tipizirane (loosely typed) jezike. To znači da sam jezik razlikuje tipove, ali da programer ne mora unapred zadavati tipove promenljivama, već ih računar automatski prepoznaje.

Takođe, u JavaScriptu je dozvoljeno da ista promenljiva tokom programa dobija vrednosti različitih tipova. Odvajanje memorije za svaku promenljivu se ne vrši pre izvršavanja programa (tj. tokom kompajliranja), već tokom izvršavanja svaki put kada promenljivoj dodelimo novu vrednost. Programski jezici koji dozvoljavaju ovakvu praksu su dinamički tipizirani (dynamic typed), ili kako smo rekli na početku - slabo tipizirani jezici.

Sada, kad smo to razjasnili, da se bacimo na posao! Osnovni ("primitivni") tipovi koje JavaScript prepoznaje su:

Tu su zatim i dve "nedefinisane" vrednosti, koje su toliko specifične da predstavljaju zasebne tipove:

Sve ostalo što može da se nađe u JavaScript programu, spada u:

Osnovne (primitivne) vrednosti

Primitivne vrednosti su nepromenljive (imutabilne). Ovde nemojte brkati nepromenljivost vrednosti sa promenljivama. Normalno, promenljiva X može u jednom trenutku imati npr. vrednost 5 a u drugom 12. Međutim, ono što nepromenljivost znači je da ne možemo naterati sam broj 5 da postane nešto drugo. I dok ovo izgleda sasvim normalno i logično, drugačija je situacija sa tekstualnim podacima, odnosno stringovima.

Programeri koji su ranije radili u jeziku C ili Pascalu, u stvari jesu navikli da stringovi budu promenljivi. U tim jezicima je sasvim moguće pristupati i menjati znakove jednog istog stringa. Ne zaboravite - u tim jezicima se stringovi tretiraju kao nizovi znakova, dok ih JavaScript posmatra kao jedinstvene vrednosti. Tako je u JavaScriptu nemoguće promeniti npr. treći znak stringa i "Fractal" pretvoriti u "Fructal".

Ono što jeste moguće je napraviti novi string i dodeliti ga istoj promenljivoj. Krajnji rezultat je isti, ali postignut na sasvim drugačiji način.

Numerički tip

Tradicionalno, počinjemo sa numeričkim tipom. Ako imate iskustva u nekom "klasičnom" programskom jeziku kao što su Pascal, C ili čak Java, iznenadiće vas da u JavaScriptu nema celih brojeva. Svi brojevi se beleže u pokretnom zarezu (64-bitni zapis dvostruke preciznosti - tzv. double). Suštinski to znači da u JavaScriptu imamo decimalne brojeve u rangu između -(253-1) i 253-1. U memoriji, to su 52 bita za mantisu, 11 bitova za eksponenet i 1 bit za znak broja. Ono što je nama značajno je da to u stvari predstavlja broj sa oko 16 preciznih cifara.

Pored trika opisanog u okviru, postoje i "legalni" celi brojevi, ali samo u obliku nizova specijalne namene, tj. tipiziranih nizova (TypedArray). Na primer, ako bismo želeli da radimo sa nizom 32-bitnih neoznačenih celih brojeva (takve vrednosti se koriste recimo za pamćenje piksela neke slike ili canvas objekta) koristili bismo poseban tip niza - Uint32Array. Za neke druge potrebe imamo i nizove 8-bitnih, 16-bitnih celobrojnih označenih ili neoznačenih brojeva, decimalne brojeve jednostruke ili dvostruke preciznosti i sl.

Numerički literali se beleže ciframa od 0 do 9, sa vodećim minusom za negativne brojeve, i decimalnom tačkom ako imamo decimale.

42 -231 3.1415

Takođe, moguće je zadati i brojeve u binarnom, oktalnom i heksadekadnom sistemu:

0b01101011 // broj 107 (binarno) 053 // broj 43 (oktalno) 0o53 // broj 43 (oktalno - po novom standardu) 081 // broj 81 - ako su cifre iznad 7, gleda se kao dekadni 0x1f // broj 31 (heksadekadno)

Inače, u JavaScriptu postoje i neke specijalne numeričke vrednosti:

Provera NaN

Najpre da elimnišemo "naivnu" proveru. Recimo da želimo da proverimo vrednost promenljive x - ako postavimo uslov if (!x)..., bićemo u problemu ako vrednost bude npr. 0, što je legitimna numerička vrednost, ali se računa kao false. Isto tako, neke druge vrednosti, koje nisu NaN takođe bivaju računate kao false - undefined i null, prazan string, pa i sam false.


  if (!x)  // radi ako je x NaN, ali i ako je 0, false, null, undefined...

Pošto NaN nije jednak "sam sebi", ne možemo pitati da li je if (x === NaN)..., jer čak i da jeste NaN, dobićemo netačan rezultat. Sa druge strane, ovu specifičnost možemo "obrnuti" u svoju korist i postaviti uslov if (x !== x).... To znači da proveravamo da li možda x nije jednak sam sebi. Pošto se to dešava samo za NaN, ovakav uslov nije loš način da proverimo da li x ima vrednost NaN. Međutim, šta ako se u budućnosti u JavaScriptu pojavi još neka vrednost koja nije jednaka sama sebi?


  if (x === NaN)  // ne radi čak i kada x JESTE NaN

  if (x !== x)  // ovo radi baš kada je x NaN! 

Jedna od "legalnih" mogućnosti je korišćenje funkcije isNaN(). Ovakav uslov bi glasio if (isNaN(x))... što nije loše, ali vodite računa kako radi ova funkcija - zadatu vrednost pokušava da pretvori u numerik i ako ne uspe, tj. ako bi se pri tom dobilo NaN, rezultat će biti pozitivan. To znači da bi neki običan "string", ni kriv ni dužan bio proglašen za NaN.


  if (isNaN(x))  // radi kada je x NaN, ali i ako je x npr. "Pera"

  if (Number.isNaN(x))  // radi samo kada je x baš NaN

Srećom i objekat Number ima metod isNaN(), koji drugačije funkcioniše, tj. vraća vrednost true samo ako zadata vrednost zaista jeste NaN. Dakle, preporučeno je da koristimo if (Number.isNaN(x))... kako bismo proverili da li x ima vrednost NaN.

Još neke specijalne numeričke vrednosti su definisane u objektu Number. Ovde ćemo ih samo pomenuti:

Tekstualni tip

Osim numeričkog, postoji i tekstualni, odnosno String tip. Ovaj tip predstavlja bilo koji tekstualni podatak u našem programu.

Za razliku od klasičnih programskih jezika, stringovi u JavaScriptu su dinamički tj. njihova veličina se ne zadaje unapred, već se menja po potrebi. Stringovi su ranije bili neograničene dužine. Tek je novi standard ECMAScript 2016 uveo ograničenje da string može biti dugačak maksimalno 253 - 1 znakova. Inače, znakovi stringa su 16-bitni UNICODE karakteri. To u praksi znači da bez ikakvih specijalnih zahteva stringovi mogu sadržati znakove svih nacionalnih pisama, a nama je svakako posebno od značaja što bez problema možemo koristiti ćirilicu i latinicu.

Još jedna razlika u odnosu na "klasične" programske jezike kao što su Pascal i C je što u JavaScriptu stringovi nisu niz znakova. Dakle, zaboravite na direktan pristup znakovima stringa:

Pascal/Delphi s := 'WEBnSTUDY'; // promenljiva s, tipa string, dobija vrednost 'WEBnSTUDY' znak := s[4]; // ima vrednost 'n' - četvrti znak stringa s[4] := '&'; // direktno menjamo četvrti znak stringa, postaje 'WEB&STUDY'

U JavaScriptu je svaki string praktično jedan celovit objekat. Možemo izdvojiti znak-po-znak stringa, ali da znate - svaki izdvojeni znak je ponovo string za sebe. Dakle u JavaScriptu ne postoji znakovni tip (ono što je u npr. Pascalu tip char - pojedinačni znak, praktično jedan bajt).

JavaScript var s = "WEBnSTUDY"; // promenljiva s, tipa string, dobija vrednost 'WEBnSTUDY' var z1 = s.charAt[3]; // ima vrednost 'n' - četvrti znak stringa var z2 = s[3]; // ima vrednost 'n' - četvrti znak stringa (ES5) s[3] = "X"; // ovo NEĆE RADITI

Notacija za izdvajanje pojedinih znakova stringa samo pomoću uglaste zagrade je "novotarija" uvedena od EcmaScript verzije 5. Inače u JavaScriptu znakovi počinju od 0, tj. prvi znak ima indeks 0, drugi je 1 itd.

JavaScript dolazi sa velikim brojem metoda za rad sa stringovima, koji su ugrađeni u same strngove. Ti metodi pokrivaju biblioteku funkcija za rad sa stringovima kakvu danas ima svaki moderan programski jezik. Treba da znate da ni jedan od tih metoda ne "mutira", tj. ne menja string za koji je zadat, već uvek kreira novi string.

String literali se zadaju unutar navodnika ili apostrofa. Poptuno je svejedno da li zadajemo string na jedan ili drugi način:

"Ovo je string." 'I ovo je string.'

Postoji još jedna vrsta literala i to nisu klasični, već šablonski stringovi (template string). Oni omogućavaju lako kreiranje stringa u više linija i interpolaciju izraza unutar stringa. Zadaju se korišćenjem naopakih apostrofa (backticks):

`Šablonski string sa vrednošću ${x+1}.` // u string ubacuje vrednost x uvećanu za 1

Kao i kod brojeva, i ovde postoji "nulta" vrednost i to je tzv prazan string, tj. string koji nema ništa između navodnika (apostrofa) - čak ni razmak:

"" // prazan string - dva navodnika jedan do drugog '' // prazan string - dva apostrofa jedan do drugog

Dužina praznog stringa je nula znakova. U logičkim izrazima prazan string se evaluira kao false.

Logički tip

Treći i naizgled najjednostavniji tip je logički tip. Ima samo dve moguće vrednosti:

Međutim, kada se vrši logička evaluacija, JavaScript takođe vrši implicitnu konverziju tipova. To suštinski znači da kada se proverava neki uslov, ako vrednost nije logičkog tipa, ona se svodi na logičku vrednost. Evo šta se "računa" kao false:

Sve ostale vrednosti se računaju kao true. Dakle, bilo kakav string, bilo koji broj (pozitivan ili negativan, čak i Infinity), bilo kakav objekat ili datum. Pazite, čak i "prazni" objekti su i dalje true. Evo nekih vrednosti za koje se pogrešno misli da će biti false:

Simbolički tip

Simboli su "novotarija" u JavaScriptu. Iako se koristi reč "simbol", ne misli se na neke čudne znakove i hijeroglife. Simboli su prosto oznake, za koje je garantovano da su potpuno jedinstvene i da praktično ne možemo imati dva ista simbola. Takođe, mi u običnom ispisu simbola (npr. u konzoli) ni ne dobijamo njegovu "pravu vrednost", već samo njegov tekstualni opis (a opisi se mogu ponavljati).

Čemu onda simboli služe? Praktična svrha im je da predstavljaju jedinstvene i neponovljive ključeve (svojstva) objekata. U JavaScriptu se često dešava da je objekat pod "uticajem" različitih delova programa, biblioteka ili frameworka. Ne bismo želeli da greškom "pregazimo" neko važno svojstvo objekta ili da neka tuđa funkcija to uradi našem objektu.

Zašto bismo uvodili neka nova svojstva u tuđ objekat? Pa, ponekad nam je potrebno da ubacimo neke dodatne podatke ili da ispratimo šta se dešava sa objektom kada tražimo greške u programu. Tada možemo uvoditi svojstva kao simbole, što nam znači jer se simboli kao ključevi ne budu pozvani pri "običnim" iteracijama kroz svojstva objekta - dakle nema šanse da se pokvari normalno izvršavanje programa. To uključuje čak i serijalizaciju objekta (predstavljanje objekta u JSON tekstualnoj notaciji) - dobijeni rezultat neće uključivati simbolička svojstva objekta.

Simbol se kreira korišćenjem ugrađenog JavaScript objekta Symbol, kome se prosleđuje neki tekstualni opis. Možemo kreirati više simbola sa istim opisom i svaki će biti jedinstven i različit.

var s = Symbol("Opis");

Tako napravljen simbol onda možemo koristiti kao ključ u objektima:

var obj = { // kreiranje objekta preko objektnog literala [s]: "Pera Perić" }; ili obj[s] = "Pera Perić"; // rad sa svojstvom postojećeg objekta

Nedefinisanost i nulti objekat

U JavaScriptu postoje dve "nulte" vrednosti koje su toliko specifične da čak predstavljaju i tipove same za sebe. To su undefined i null.

Vrednost undefined

Ova vrednost opisuje stanje nedefinisanosti. Vrednost undefined imaju:

Provera nedefinisanosti

Vrednost undefined se u logičkoj proveri evaluira kao false. Međutim, uz to će biti i prijavljena greška. Postoji više načina da proverimo da li je neka promenljiva nedefinisana. Najpre, možemo proveriti da li je njena vrednost ekvivalentna undefined:


  if (x === undefined)   // izbacuje grešku - x nije deklarisano
  
  var y;
  if (y === undefined)   // prolazi - y nije definisano ali jeste deklarisano

Ako je promenljiva nedeklarisana, "izbaciće" grešku i prekinuti izvršavanje. Međutim, kada je promenljiva samo deklarisana, takođe će biti undefined, ali u ovom slučaju nema greške i izvršiće se if-blok. Pazite, obavezno je koristiti striktnu jednkost ("===" - tri znaka jednakosti) pošto bi sa običnom jednakošću ("==" - dva znaka jednakosti) i neke druge vrednosti, poput null bile izjednačene sa undefined.

Ipak, postoji jedan mali problem. U starijim verzijama JavaScripta, nesmotreni programer je mogao da redefiniše sam undefined, odnonso da mu dodeli neku sasvim drugačiju vrednost. Zbog toga postoji bezbedniji način, a to je korišćenje operatora void koji bilo koji izraz evaluira ali kao vrednost uvek bude "originalni" undefined. Tako da to onda postaje malo sigurniji način u odnosu na gorenavedeno.


  if (x === void 0)   // izbacuje grešku - x nije deklarisano
  
  var y;
  if (y === void 0)   // prolazi - y nije definisano ali jeste deklarisano

Srećom, od verzije ECMAScript 5, undefined pstaje read-only, tako da ga postaje nemoguće promeniti. Drugi način je korišćenjem operatora typeof, koji nam služi za proveru tipova:


  if (typeof x === "undefined")    // uvek prolazi - čak i kada x nije ni deklarisano

Ovo je mnogo "čistiji način - pre svega neće izbaciti grešku ako je promenljiva nedeklarisana - sve "prolazi" bez problema u svakom slučaju.

Vrednost null

Vrednost null je jedina vrednost tipa Null. Ovo je praktično "nulti" objekat. Nemojte mešati ovu vrednost sa "praznim" objektom:

var x = null; // "nulirani" objekat var y = {}; // "prazan" (naizgled), ali i dalje pravi-pravcati objekat

Za razliku od undefined, null nije zaista nešto "nedefinisano", već pre nedostatak vrednosti. Služi nam da opišemo situaciju kada bi neka promenljiva trebala da bude referenca na objekat, ali iz nekog razloga taj objekat ne postoji.

Provera vrednosti null

Inače, ne brinite - null ćemo mnogo lakše da "hendlujemo" od undefined ili NaN vrednosti. Kada želimo da proverimo da li je nešto null, dovoljno je da to pitamo (koristeći striktnu jednakost):


  if (x === null) { ... }

U slučaju da je x zaista null, if-blok će se izvršiti bez problema i bez "ispaljivanja" greške.

Vodite računa da kod provere uvek koristite baz striktnu jednakost, pošto bi u suprotnom null mogao lako da se pobrka sa undefined:


  null == undefined;    // true - obična jednakost ih poistovećuje
  null === undefined;   // false - ovako i treba da bude
  null == false;        // true - null se u logičkim proverama poistovećuje sa false
  !null == true;        // true - "not null" se poistovećuje sa true
  isNaN(1 + null);      // false - aritmetička operacija sa null neće kreirati NaN, 
                        // pošto će se null evaluirati u 0

Međutim, ako pokušamo da proveravamo null, operatorom typeof, to će nas uvesti u probleme, pošto iako je null tip za sebe, typeof ga tumači kao object:


  if (typeof null === "object") { ... }

Rekli smo da null obično ne "ispaljuje" grešku, ali pošto se od promenljive koja ima vrednost null očekuje da bude objekat, pokušaj pristupa nekom svojstvu objekta koji je u stvari null, rezultuje greškom u programu.

var obj = null; // "nulirani" objekat obj.x = "vrednost"; // greška!

Iako operator typeof "čita" null kao objekat, ne zaboravite - null je tipa Null, a ne zaista objekat. To znači da null promenljivoj ne možemo dodavati svojstva, kao što to inače radimo sa objektima.

Objekti

Kao što smo rekli na početku, sve ostalo što može da se nađe u JavaScript programu, spada u tip objekta. O objektima će biti mnogo više reči u lekcijama koje tek dolaze. Za sada je dovoljno da znate da je objekat jedna "kompleksna promenljiva" koja u sebi može sadržati više "potpromenljivih", odnosno može se sastojati iz više vrednosti. Ti "elementi" objekta mogu biti čak i drugi objekti (podobjekti), pa čak i funkcije.

Objekat može biti kreiran na više načina, a najjednostavniji je navođenjem objektnog literala:

var x = {}; // "prazan" objekat var obj = { // objekat sa tri potpromenljive ("svojstva", odnosno "atributa") ime: "Jovan Jovanović", visina: 182, težina: 96 };

Čak su i funkcije u JavaScriptu jedna specijalna vrsta objekta. Kao objekti mogu biti kreirane i primitivne vrednosti - brojevi, odnosno stringovi.

Za sada toliko - objektima ćemo se baviti mnogo više kada dođe vreme.

  1. MDN web docs, JavaScript data types and data structures
  2. JavaScript Info, Data Types
  3. MDN web docs, Number
  4. MDN web docs, typeof
Svi elementi sajta Web'n'Study, osim onih za koje je navedeno da su u javnom vlasništvu, vlasništvo su autora i ne smeju se koristiti, u celosti ili delimično bez pismenog odobrenja autora. To uključuje tekstove, slike, ilustracije, animacije, prateći grafički materijal i programski kod.
Ovaj sajt koristi tehnologiju kolačića (cookies). Detaljnije o tome možete pročitati u tekstu o našoj politici privatnosti.