Chrome DevTools

Uvod

chrome devtools

U ovome članku je napravljen pregled specijalizovanih alata u okviru “Chrome” browsera, pod nazivom “DevTools”. Chrome DevTools su nezamenjivi set alatki namenjeni web developerima kao pomoć u svakodnevnom radu. Kroz DevTools je omogućen pregled HTML stranice i rad sa DOM elementima, kao i pristup svim CSS svojstvima elemenata.
U ovom paketu alata je naručita pažnja posvećena delu za debagovanje JavaScript koda. Koristeći ovoj alat je omogućeno definisanje raznih načina prekidanja izvršavanja progamskog koda (tzv. breakpoint), što znatno olakšava rad web developerima pri otklanjanju bagova na vebsajtovima. Pri svakom prekidu je omogućen uvid u vrednosti promenjiva kao i njenih oblasti definisanosti.
Pored ovoga postoje sekcije vezane za praćenje performansi web aplikacije, kao i pregled razmene podadaka izmedju klijenta i servera.

General

Global shortcuts

Global Shortcut Windows
Open whatever panel you used last F12 or Control+Shift+I
Open the Console panel Control+Shift+J
Show General Settings dialog ?, F1
Next panel Ctrl + ]
Previous panel Ctrl + [
Backward in panel History Ctrl + Alt + [
Forward in panel history Ctrl + Alt + ]
Change docking location Ctrl + Shift + D
Open Device Mode Ctrl + Shift + M
Open Command Menu Ctrl + Shift + P
Toggle Console / close settings dialog when open Esc
Refresh the page F5, Ctrl + R
Refresh the page ignoring cached content Ctrl + F5, Ctrl + Shift + R
Text search within current file or panel Ctrl + F
Text search across all sources Ctrl + Shift + F
Pretraga fajlova na stranici Ctrl + P
Pretraga funkcija u okviru fajla otvorenog u editoru Ctrl + Shift + O
Zoom in (while focused in DevTools) Ctrl + +
Zoom out Ctrl + -
Restore default text size Ctrl + 0

Pretraga svih fajlova

Pretraga prema ključnoj reči kroz sva dokumenta je omogućena prečicom Ctr + Shift + F, nakon čega se otvara sekcija za pretragu. Nakon zahteva za pretragu po nekoj ključnoj reči u sekciji se pojavljuju izlistani rezultati. Dovoljno je kliknuti na neki od rezultata i otvoriće se odgovarajući fajl.

pretraga

Inspector settings

Otvaranje settings prozora

Settings prozor se najlakše prikazuje sa F1 ili klikom na tri vertikalne tačkice u gornjem desnom uglu prozora inspektora.

settings

Čuvanje koda i nakon reload-a

Ako želimo da sačuvamo kod unutar console i nakon reload-a stranice, potrebno je da se u settings sekciji “čekira” opcija “Preserve log upon navigation” pod tabom Console.

Blackboxing script

Blackboxing script je postupak sa kojim pri debug-ovanju “step by step”, možemo da naglasimo Chrom DevTools-u koje fajlove da ne proverava, jer verovatno greška nije tamo već u našim fajovima. Fajlovi koje treba ubaciti u blackbox su obično to third part library kao što je jQuery… Kada se neki fajl stavi u black box, onda se pri “stepping into/out/over” debuger neće zaustavljati na tim fajlovima.

I način

Potrebno je otvoriti Chrom DevTools settings (F1) i izabrati tab Backboxing nakon čega treba napisati ime fajla ili napraviti odgovarajući Regex patern.

blackboxing

Primer za često korišćene paterne je:

  • /jquery\.js$
  • \.min\.js$ — for all minified sources
  • node_modules and bower_components — for dependencies
  • ~ — home for dependencies in Webpack bundle
  • bundle.js — it’s a bundle itself (we use sourcemaps, don’t we?)
  • \(webpack\)-hot-middleware — HMR
II način

Dok smo u debuger-u desni klik na skriptu prikazanu u okviru “Call Stack”, nakon čega izaberemo “blackbox script”

blackboxing

Definisanje break point-a

Postoje više načina za postavljanje breakpoint-a:

1) Breakpoint na liniji JavaScript koda

Ovaj breakpoint se aktivira kada označimo mesto u kodu gde želimo da zaustavimo JS, tako što u okviru editora klikom na redni broj linije koda obeležimo gde da se zaustavi izvršavanje programa. Više o ovome pročitajte na pficijalnoj stranici

Uslovni brakpoint

Medjutim postoji opcija da se izvrši “uslovni breakpoint” koji zavisi od zadatog uslova. Desnim klikom na break point se otvara prozor gde možemo da izaberemo opciju “edit breakpoint”. Nakon čega se prikazuje polje za unos odredjenog uslova. Breakpoint će se aktivirati samo ako je uslov zadovoljen. Više o uslovnomom brakpointu pročitajte na oficijanoj stranici

uslovni brak point

2) Breakpoint na elementu DOM-a

Breakpoint možemo dodati obeležavajući HTML kod. Da bi mogao da zaustavi izvršavanje programa taj deo HTML koda treba da je povezan sa JavaScript kodom (obično je to neki dinamički generisan element). Ovaj breakpoint se aktivira kada dodje do promene na označenom HTML elemenatu (pa čak i kod njegove dece).

Na sam elemenat uradimo desni click, nakon čega izaberemo opciju Break on…, pa onda neku od podopcija. (Pogledaj sliku) Opcija “subtree modification” prati promene nad decom tog elementa. (changes to child elements). Ukoliko se izabere opcija “attributes Modifications” onda se prate promene na atributima tog elementa. Dok pri izboru opcije “node removal” se prati trenutak kada dolazi do uklanjanja označenog elementa.
Kada dodje do promene na tom HTML kodu, izvršavanje javascript-a se zaustavlja i otvara se JS fajl odgovoran za tu promenu, sa obeleženim mestom u kodu zaslužnim za tu promenu. Više o ovome možete pogledati ovde

dom breakpoints

3) Breakpoint pri XHR zahtevu

Postoji mogućnost da napravimo brakpoint koji će se aktivirati pri svakom ajax zahtevu. Za aktiviranje ovakvih breakpoint-a je potrebno da u sekciji “XHR breakpoints” ne definišemo uslov, nakon čega će se pojaviti opcija “Any XHR”.
Takodje može da se filtriraju brakpoint-i, ako definišemo odredjeni string patern za specifičnu XHR url adresu. Više o ovome pročitajte na oficijelnoj stranici

XHR breakpoint

5) Breakpoint pri exception

Ovaj brekpoint se aktivira na liniji koda koji je izbacio exeption. Više o ovome pročitajte na oficijelnoj stranici

breakpoint on exception

Elements TAB

Shortcuts

Elements Panel Windows
Edit attribute Enter, Double-click on attribute
Hide element H
Toggle edit as HTML F2

Event listeners za debagovanje dogadjaja

U okviru Elements Panel-a, možete da pregledate dogadjaje na nekom elementu, jednostavnim izborom tab elementa “Event listeners”, dok klikom na link možete da vidite i samu handler funkciju.
Klikom na “remove”, možemo da privremeno uklonimo registrovani event handler, što je korisno za brzo proveravanje da li je event handler uzrok neočekivane greške.
Ako vaš kod koristi i neku biblioteku kao što je jQuery, DevTools može da sakrije event handlere biblioteke a da prikaže samo naše (ovo nije uvek izvodljivo). Ovo se dobija tako što se selektuje polje za potvrdu “Framework listeners”.

event tips

Filtriranje CSS svojstava

Dok se nalazimo u “Styles” sekciji, mozemo da brzo pretražujemo CSS svojstva. Jednostavnim upisom naziva svojstva unutra input-a za filter na vrhu sekcije (pogledaj sliku). Odmah po unosu filtera se fitrirana svojstva istaknu, aktivana malo jačnom bojom.

filtering css

Console TAB

Shortcuts

Console & Editor section Windows
Open the Console panel Control+Shift+J
Selektovanje istih reči CTRL + D
Brisanje Consle CTRL + L
Toggle edit as HTML F2

Console loging levels

Izbor sadržaja koji želimo da vidimo u konzoli se vrši u padajućem meniju loging levels. Ovaj padajući meni se nalazi na vrhu konzole sa desne strane filtera. Naručitu pažnju privlači opcija Verbose, koja je “najšira” opcija i prikazuje čak i tekstualni opis odredjenih problema.

loging levels

Filtriranje izveštaja konzole

Ukoliko se u konzoli javljaju greške ili upozorenja od “third party” izvora na koje ne možete da utičete pa vas zbog toga i ne interesuju izveštaji o njima, možete da ih filtirate. Izbor opcije za fitriranje se dobija desnim klikom na izveštaj u konzoli. Nakon toga se dobija sekcija gde se pojavljuje opcija za filter izveštaja na koji smo kliknuli.
U koliko posle nekog vremena ipak želimo da vidimo sve izveštaje, dovoljno je da se ponovo izabere desnim klikom sekcija za filter, nakon čeka je potrebno izabrati “unhide all”.

filtriranje izveštaja

Štampanje u konzoli

consoloe.log()

Najčešći način za štampanje bez nekog formatiranja:

console.table()

Primer

Ova metoda štampa pregledno objekat sa svim svojstvima:

stampanje console.table

Medjutim ukoliko objekat ima puno svojstava tabela može da bude nepregledna, tada je dobro izabrati kolone koje nas interesuju. Izbor svojstava koje želimo da prikažemo se definiše kroz drugi argument:

console.dir()

Štampa željeni objekat u stilu direktorijuma:

console.trace()

Console.trace() izraz se stavlja unutar koda, a u konzoli ispisuje ceo call Stack koji je pozvao taj kod.

Primer

U ovome primeru je stavljena funkcija console.trace() u okviru funkcije sumFunction(), tako da će u konzoli ispisati creo call stack koji pozvao funkciju sumFunction():

U konzoli se ispisuju funkcije prema obnutom redu pozivanja, a pored svake funkcije je link do nje:

console.error()

Štampa poruku isto kao console.log(), stim što je formatiran kao error

console.assert()

Funkcija koja izbacuje grešku ako se ne zadovolji odredjeni uslov:

console.time()

tajmer

Ova funkcija se koristi za merenje vremena izvršavanja nekog dela koda. Potrebno je pre početka koda dodati:

cosnole.time(‘nekiNazivTajmera’)

nakon ovoga sledi kod kome merimo vreme izvršavanja, a posle njega:

console.timeEnd(‘nekiNazivTajmera’)

Monitoring dogadjaja iz console

monitorEvents()

Metoda monitorEvents() daje podatke o elementu koji je targetiran sa event-om.

Primer

Ili čak:

monitor event

Za prekid monitoringa koristimo naredbu:

Monitor funkcije

Ako želimo da pratimo pozivanje odredjene funkcije koristimo metodu monitor(nazivFunkcije). Ova metoda nam ispisuje u konzoli svaki put kada je pozvana funkcija i koji argumenti su joj prosledjeni.
Npr.
function nazivFunkcije called with arguments: [object MouseEvent] // funkcija je event handler

Za prekid monitoringa koristimo naredbu:

Source TAB

Shortcuts

Sources Panel Windows
Pause / resume script execution F8, Ctrl + \
Step over next function call F10, Ctrl + '
Step into next function call F11, Ctrl + ;
Step out of current function Shift + F11, Ctrl + Shift + ;
Select next call frame Ctrl + .
Select previous call frame Ctrl + ,
Toggle breakpoint condition Click on line number, Ctrl + B
Edit breakpoint condition Right-click on line number
Delete individual words Ctrl + Delete
Comment a line or selected text Ctrl + /
Save changes to local modifications Ctrl + S
Save all changes Ctrl + Alt + S
Go to line Ctrl + G
Search by filename Ctrl + O
Pretraga funkcija u okviru fajla otvorenog u editoru Ctrl + Shift + O
Jump to line number Ctrl + P + :number
Jump to column Ctrl + O + :number + :number
Go to member Ctrl + Shift + O
Close active tab Alt + W
Run snippet Ctrl + Enter

Ovaj TAB se sastoji od tri sekcije: Source/Snippets section, Editor section i Debuging section.

source-tab

a) Source – “Snippets section”

Add local source files to workspace

“Add local source files to workspace” ustvari znači da je omogućen direktan pristup lokalnim fajlovima iz samog browser-a. Povezivanje je moguće za JS i stylesheet fajlove, dok za DOM tj. HTML fajl nije primenjiv. Da bi povezali fajlove iz “sources” tab-a unutar Chrom DevTools-a sa lokalnim fajlovima i tako sačuvali promene na JS fajlovima i nakon ponovnog učitavanja browser-a, potrebno je uraditi sledeća dva koraka:

  1. Add Folder to Workspace

    Sledeći postupak ukazuje browseru gde se nalazi na naš lokalni folder sa fajlovima.

    1. Right-click in the left-side panel.
    2. Select Add Folder to Workspace. Alternativa ovome postupku je da se iz explorer-a prevuče (drag and drop) folder u inspektor
    3. Choose location of local folder that you want to map.
    4. Click Allow to give Chrome access to the folder.
  2. Map to File System Resource

    map to resourse
    Drugi deo postupka je vezan za fajlove pojedinjačno. Koristeći sledeći postupak povezujemo odredjeni fajl sa browser-om. Nakom toga svi fajlovi mogu da se modifikuju iz source panela, pa čak i css fajlovi direktno iz Elements/Styles panela.

    1. Right-click or Control+click on a file in the Sources left-side panel.
    2. Choose Map to File System Resource.
    3. Select the local file in the persistent workspace.
    4. Reload the page in Chrome.

    NAPOMENA:
    Fajlovi sa .scss ekstenzijom se ne mogu editovati iz Elements/Styles panela već samo css!

Da bi se sačuvale promene napravljene u browseru u okviru Sources panela potrebno je nakon desnog klika izabrati opciju Save.
Pored ove funkcionalnosti iz workspace može da se kreiraju novi fajlovi, brišu stari kao i da se prave backup kopije fajlova direktno na hard disku.

NAPOMENA:
Ovaj ceo postupak će omogućiti da se iz browsera menjaju lokalni fajlovi na disku, stoga ukoliko želite da sačuvate postojeće stanje NAPRAVITE KOPIJU FAJLA PRE PROMENA!

Snippet u browseru

U sklopu Chrome DevTools može da se sačuva deo koda i nakon refresh-ovanja stranice. Sačuvani kod kao snippets može da se samostalno pokrene dok smo na bilo kojoj stranici.

source snippet img

Online snippets baza

Bazu korisnih snippets-a možete pronaći na https://bgrins.github.io/devtools-snippets/. Ukoliko sačuvamo neki od pripremljenih snippeta, kasnije možemo da ih pokrenemo na bilo kojoj stranici. Jedan od korisnih snippeta je vezan za pregled perfomansi web aplikacije:

snipetts

b) Source – “Editor section”

Postavljanje kursora na više mesta odjednom sa CTRL + levi klik mišem. Višestruko biranje istog sadržaja sa CTRL + D. Odlazak na zatvarajući ili otvarajući tag sa CTRL + M.

edtors trics

c) Source – “Debuging section”

a) Watch expression (Praćenje vrednosti nekog izraza)

watch

b) Call Stack

Call Stack je sekcija u kojoj je prikazano kako se došlo do trenutno zaustavljenog reda pri debug-ovanju, koje su sve funkcije bile pozvane do tada. Ukoliko očekujemo da pratimo i asihrone pozive potrebno je da čekiramo input Async. Desnim klikom na Call Stack sekciji otvaramo dropdown na kome možemo da izaberemo:

  • Restart Frame – restartovanje koda i svih vrednosti tik ispred brakpoint-a
  • Copy Stack trace – kopiramo ceo Stack koji je u tom trenutku
  • Blackbox script – drugi način da naglasimo Chrom DevTools-u koje fajlove da ne proverava

callstack

c) Scope promenjivih

Dok je program pauziran na nekoj liniji koda, u delu “Scope” se mogu pregledati koje su trenutne promenjive u lokalnom, globalnom i closure opsegu (domenu).

scope

d) Breakpoints

U ovoj sekciji su prikazani svi breakpoint-i .

e) XHR Breakpoints

U ovome delu se se definišu ali i pregledaju postojeći brakpoint-i koji su vezani za AJAX zahteve. Ukoliko postoji AJAX zahtev sa zadatom url adresom, browser će zaustaviti izvršavanje programa kada se pošalje zahtev. Možemo na[praviti breakpoint-e na svaki AJAX zahtev ukoliko napravimo novi breakpoint ali polje gde se unosi url adresa ostavimo prazno.

XHR breakpoint

d) DOM Breakpoints

Ova sekcija prikazuje sve brakpoint-e definisane na DOM-u.

dom breakpoints

f) Event Listener brakpoint

U ovome delu su izlistani svi mogući dogadjaji, potrebno je samo da označimo na koju vrstu dogadjaja želimo da napravimo brakpoint. Ovaj brakpoint se aktivira na delu koda gde se nalazi event listener koji treba se izvrši odmah po dogadjaju.

eventlistener brakpoint

Network Tab

Network tab se bavi vremenom i redosledom učitavanja svih fajlova koji dolaze sa mreže. Nakon učitavanja stranice ispisuju se svi fajlovi koji su stigili, kao i detalji o njima: headers, vreme učitavanja. Možemo da vidimo tzv. “waterfall” prikaz, kao i capture filmstrip u toku vremena. Učučivanjem neke od opcija za filtriranje možemo jednostavno da izaberemeo koji nas fajl interesuje. Postoji mogućnost imitacije nekog drugo tipa mreže (npr.3G, 2G…) i rezultata koji bi se dobili da su te mreže izabrane.

network tab

Tips & Tricks

Editovanje sadržaja iz browsera

Dodavanjem atributa contenteditable="true" bilo kom HTML elementu, taj elemenat postaje editabilan iz samog browser-a. Da bi ste “na brzaka” isprobali sadržaj možemo dodati atribut kroz elements tab ili čak koroz konzolu:

document.body.contenteditable = true
editovanje sadrzaja


Promise i asinhrono programiranje

Uvod


pyramid of doom

U JavaScript-u postoji izraz za deo koda sa ugnježdenim callback funkcijama pod nazivom “callback hell” ili “pyramid of doom”. Debagovanje takvog programskog koda pa čak i samo razumevanje je veoma otežano. Sa ES2015 standardom je došla nova syntax-a pod nazivom “promise” (srp. obećanje), koja sa svojim API-jem obezbedjuje bolji i pregledniji način za organizovanje callback funkcija. Ovo se naručito primećuje u radu sa asinhronim operacijama jer sa promisima sintaksa veoma liči na standardnu sinhronu sintaksu.

Primer – “callback hell”

Najpoznatija i najčešća primena callback funkcija je “hendlovanje” akcija nakon izvršenog dogadjaja. Upravo je “hendlovanje” medjusobno zavisnih dogadjaja najčešće uzrok “callback hell-a”. U ovom primeru je prikazan izgled takvog koda:

Šta je Promise?

Promise je javascript objekat koji predstavlja “placeholder” za rezultate asihrone funkcije sve dok traje izvršavanje asinhrone operacije.

Promise je sinhrono vraćen objekat pri asinhronoj operaciji, koji predstavlja privremenu zamenu za moguće rezultate te asinhrone operacije.

Promise umesto krajnje vrednosti, daje obećanje da će dostaviti tu vrednost u nekom trenutku u budućnosti. Pošto su promise objekti privremena zamena za buduću eventualnu vrednost, to nam omogućava da preko njega zakačimo handler-e za budući rezultat asinhrone operacije. Sa ovom novom mogućnosti smo skoro izjednačili asinhrone operacije sa sinhronim. Sada i sinhrone i asinhrone operacije mogu da vraćaju neku vrednosti, stim što sinhrone odmah vraćaju krajnji podatak a asinhrone “placeholder” za budući podatak.

promise state

Asinhrona funkcija može imati dva moguća krajnja rezultata, a to su “uspešno izvršena operacija” ili “neuspešno izvršena opercija”, dok se promise može nalaziti u jednom od tri stanja:

  • Pending – kada se asinhrona radnja još uvek izvršava
  • Fulfill – kada je asinhrona radnja završena uspešno
  • Reject – kada je asinhrona radnja neuspešno završena greškom

Ceo promise mehanizam se može podeliti na dva dela:

  1. Kreiranje promisa unutar asinhrone funkcije
  2. Korišćenje kreiranog promisa (kod se nalazi izvan asinhrone funkcije)

Kreiranje promisa

Da bi se budući krajnji rezultat asinhrone funkcije zamenio sa promise objektom, potrebno je da funkcija vrati novi promise objekat kroz svoj kod:

Svakom novom obećanju se kroz parametar prosledjuje funkcija (tzv. executor funkcija) koja obradjuje samu asinhronu operaciju i buduće rezultate te asinhrone operacije. Nama je interesantan deo gde obradjuje eventualne rezultate asinhrone operacije, kada u zavisnosti od uspešnosti operacije poziva jednu od dve funkcije koje su joj prosledjene kao parametri:

  • Funkcija resolve() se poziva u delu koda koji obradjuje uspešno završenu asinhronu operaciju. Parametar ove funkcije predstavlja dobijeni podatak iz uspešno završene operacije, stoga se funkcija resolve() koristi da kroz svoj parametar prosledi rezultujući podatak odgovarajućoj “handler” metodi npr. then() ili Promise.all()…
  • Funkcija “reject()” se poziva u delu koda koji obradjuje slučaj kada se pojavi problem sa izvršavanjem asinhrone operacije. Ona kroz svoj parametar prosledjuje razlog neuspešnosti asinhrone operacije odgovarajućem “hendleru”, najčešće catch() metodi.

Korišćenje promisa

Korišćenje promisa podrazumeva obradu eventualnih rezultata dobijenih po završetku asinhrone operacije.

Promise.prototype.then()

Promise reaguje na promenu svoga stanja pozivajući callback funkciju. Ukoliko je nakon promene stanja promise u stanju fullfiled poziva se metoda then(). Ova metoda prihvata dva parametra “onFulfilled” i “onRejected” koji su tipa funkcije.

Prva funkcija onFulfilled “hendluje” uspešno završenu asinhronu operaciju. Ona prihvata jedan parametar a kroz njega joj se prosledjuje podatak dobijen asinhronom operacijom. Dok druga funkcija “onRejected” “hendluje” neuspešno završenu asinhronu operaciju i takodje prihvata jedan parametar kroz koji joj se prosledjuje razlog neuspeha.

Primer

U ovom primeru kroz parametar funkcije resolve() prosledjujemo podatak (xhr.response) funkciji onFulfilled(), dok kroz parametar funkcije reject() prosledjujemo tip greške “new Error(xhr.statusText)” funkciji onRejected().

Promise.prototype.catch()

Ukoliko je nakon promene stanja, promise u stanju rejected, poziva se metoda catch().

Metoda catch() kao parametar prihvata callback funkciju (za koju se koristi naziv “onRejected()”), koja je zadužena za prihvatanje i obradu greške.

OBJAŠNJENJE:
Iako metoda then() može da “hendluje” pored uspešnih rezultata i neuspešne, to se ne koristi tako često. Najčešće se metoda then() koristi da “hendluje” samo uspešan rezultat (koristi se samo prvi parametar), dok se za slučaj neuspešne operacije koristi catch() metoda.

Ili malo preglednije napisano:

Primer

U primeru je prikazano hendlovanje ajax asinhrone operacije sa promisom koji koristi then() i catch() metodu ali i sa “zastarelim” callback funkcijama:

U ovom primeru je preko parametra funkcije resolve() prosledjen “xhr.responseText” u “data” parametar then() metode, a preko parametra funkcije reject() je prosledjen “new Error(“Network error”)” u “err”. parametar catch() metode


Ulančavanje promisa

Pošto metode then() i catch(), uvek vraćaju novi promise, one se mogu ulančavati. Koristeći ovu mogućnost se otvaraju vrata da se na elegantan nači reši problem sa mnogo ulančanih dogadjaja koje pozivaju callback funkcije, poznatiji kao “callback hell”.

Primer

Promise.resolve()

Promise.resolve(value) je metoda koja pravi promise od drugačijih tipova. Može da primi tri različita tipa kao parametar, nakon čega vraća promise:

  1. Promise.resolve(vrednost)
    Kada se ovoj metodi prosledi neka vrednost, ta vrednost će biti prosledjena then() funkciji kroz njen parametar.
  2. Promise.resolve(drugiPromise)
    Kada se prosledi neki drugi promise tada se kroz parametar metode then() prosledjuje eventualno stanje prihvaćenog promise objekta. Ovo je najčešći slučaj, jer se koristi za konvertovanje promisa kreiranih od strane drugih biblioteka.
    Primer

    Obratiti pažnju na redosled štampanja u konzoli, redosled je drugačiji nego što je u kodu, zato što je “then handlers” pozvan asinhrono. Više o ovome pogledajte u članku Osnove asinhronog programiranja u JavaScript-u

  3. Promise.resolve(thenableObject)
    Ova metoda može da prihvati kao parametar i tzv. “thenable object”:
    Primer

Promise.reject()

Promise.reject(reason) uzima za “reason object” String ili Error, a vraća promise koji se nalazi u stanju rejected uz odgovarajući razlog odbijanja.

Promise.all()

Promise.all(iterable) kao parametar uzima iterabilnu listu promise objekata. Promise.all() metod vraća jedan promise u trenutku kada su svi promisi sa liste uspešno rešeni. Promise.all() metoda će vratiti “promis”, čak i kada joj se prosledi prazna lista ili element koji nije promise (pogledaj primer). Kod ove metode redosled izvršavanja liste promisa nije zagarantovan, jedino je zagarantovano da će vratiti krajnji “promis”, kada svi promisi sa liste budu fullfiled.

Primer

U slučaju da je jedan promise iz liste u stanju rejected, metoda Promise.all() vraća odbijen promise bez obzira da li u listi postoji neki promis koji je uspešan. Uz odbijen promis se vraća i razlog odbijanja. U slučaju da ima više odbijenih promisa, prosledjeni razlog je od prvog odbijenog promisa!

Asinhronost i sinhronost Promise.all()

Promise.all() se u svim slučajevima ponaša asinhrono osim u slučaju kada je umesto liste prosledjen prazan objekt, tada se ponaša sinhrono.

Primer

Obratite pažnju da je pri direktnom sinhronom stampanju “prazanPromise” u stanju fullfiled, dok je standardni promise pod nazivom “nekiPromise” u stanju pending.

Kada koristiti “Promise.all()” a kada “Promise.prototype.then()”?

Izbor se svodi na to da li je bitan redosled izvršavanja promisa ili ne. U sledećem primeru je bitan redosled izvršavanja promisa pa se koristi Promise.prototype.then():

Dok u narednom primeru za pravljenje betona nije bitan redosled kada će koji promise biti završen, već je samo bitan trenutak kada su svi spremni, pa je preporuka da se koristi Promise.all():

Promise.race()

Promise.race(iterable) je metoda koja takodje kao parametar uzima iterabilnu listu promise objekata a vraća obećanje. Ova metoda vraća rezultat koji “stigne prvi”, nebitno da li je uspešan ili ne. Pa tako može biti vraćen promise ili sa krajnjim podatkom kod uspešno izvršene asinhrone operacije ili sa razlogom za neuspešnu operaciju.


Klase u JavaScript-u

Uvod

Klase u javascript-u

Klase u JavaScript-u su samo drugačiji način predstavljanja konstruktorske funkcije i metoda iz “prototype objekata”, ali bez suštinske promene samog mehanizama nasledjivanja. Pozadina nasledjivanje klasa je poznati mehanizam “delegiranje metoda” kroz “prototype lanac nasledjivanja”.
U JavaScript-u rezervisana reč “class” samo ukazuje na to da je upitanju specijalna vrsta funkcije, koja za razliku od obične funkcije ne može da se pozove (invoke), nego se jedino može koristiti uz rezervisanu reč “new”.
Ova funkcionalnost je ubačena u jezik sa ES2015 standardom, sa namerom da poboljša čitljivost i olakša pisanje objektno orjentisanih programa. Pri definisanju izgleda sinktakse dizajneri standarda su se vodili idejom da naprave takvu sinktaksu koja će ličiti na sinktaksu većine “klasnih” jezika”, i tako pomoći programerima koji već programiraju u nekom “klasnom” jeziku” da lakše usvoje JavaScript sinktaksu.
Ako u narednim primerima uporedimo delove koda pisane različitim sintaksama, možemo uočiti da je bolja čitljivost klasne sintakse u odnosu na ES5 sintaksu:

Primer: ES5 sintaksa

Primer: Klasna sintaksa

Izgled klase je veoma sličan sintaksi kreiranja objekta prema ES5 standardu, mada je čitljiviji zbog manje redova i izbačenih nepotrebnih delova:

NAPOMENA:
Za razliku od drugih “klasnih jezika”, kreiranje objekata u Javascript-u (čak i kada se koriste klase) nije statičko tj. nije nepromenjivo nakon deklarisanja objekta. U JavaScript-u objekat nakon instanciranja ostaje “vezan” za klasu, svojim “prototype objektom” preko lanca nasledjivanja. Stoga, ukoliko naknadno dodamo ili promenimo neku metodu u samoj klasi, tu promenu će osetiti svaki objekat instanciran na osnovu te klase.

Osnovne karakteristike

Kreiranja klasa

Pošto su klase ipak samo funkcije, kao i kod svih funkcija postoje dva načina za njihovo kreiranje:

  1. Function declarations

    Ovo je najčešći način pisanja klasa:

    Osnovna razlika izmedju deklaracije funkcije i deklaracije klase je ta što se klase ne “hoist-uju” pri kompajliranju na početak programskog koda kao funkcije. Tako da treba obratiti pažnju da se klasa definiše pre nego što se korisiti “new” za kreiranje novog objekta.

  2. Function expressions

    Ovaj pristup se redje koristi, ali potpuno legalan način za kreiranje klasa:

    Kao i kod obične “function expressions” ni ovde nema hoist-ovanja.

NAPOMENA:
Telo klase se izvršava u “strict mode”.

Metode

Obične metode

Metode definišemo kao funkcije, ali bez ključne reči function. Mada treba napomenuti da metode unutar klase imaju “enumerable” svojstvo setovano na false, što znači da u startu nisu dostupna “for..in” petlji.

Constructor metoda

Constructor je specijalna metoda koja kreira i inicijalizuje objekat. Ova metoda je pandan konstruktorskoj funkciji iz ES5, u njoj se definiše sve što je potrebno da se inicijalizuje novi objekat, uz napomenu da može postojati samo jedna “constructor” metoda unutar jedne klase.

Statičke metode

Statičke metode su metode koji ne pripadaju instanciranom objektu, već samoj klasi, stoga im se ne može pristupiti iz instanciranog objekta. Jedini pristup ovim metodama je preko same klase. Ovakve metode se definišu korišćenjem rezervisane reči “static” ispred naziva metode.

Get i Set metode

U mnogim programskim jezicima se pristup privatnim svojstvima ostvaruje uz korišćenje specijalnih metoda tzv. “get-era” i “set-era”. Tako je i kod JavaScript-a, kod koga se ovakve metode u okviru klase označavaju dodavanjem rezervisane reči “get/set” ispred samog naziva metode.

Primer

NAPOMENA:
Get/Set metode se definišu u okviru klase kao metode, ali im se pristupa na isti način kao da su svojstva objekta (properties).
a) Ovakvoj metodi se unutar neke druge metode pristupa kao da je obično svojstvo objekta:

b) “Get” metoda se u novo generisanom objektu takodje poziva kao svojstvo objekta:

c) Čak se i “set” metodi pristupa kao dodeljivanje vrednosti običnom svojstvu objekta:

Nasledjivanje klasa

Sintaksa

Za nasledjivanje klasa je potrebno da se u samoj deklaraciji klase koristi ključna reč extends i naziv objekta koji se nasledjuje. Deklaracija u narednom primeru Naslednik extends Roditelj nam “govori” da se objekat Naslednik.prototype povezao za Roditelj.prototype objekatom.

Pri kreiranju nove klase koja nasledjuje neku drugu klasu imamo obavezu da pri definisanju konstruktorske funkcije moramo unutar nje pozvati konstruktorsku funkciju roditeljske klase. Rezervisanja reč super ukazuje na roditeljsku konstruktorsku funkciju, a za pozivanje konstruktora bazične klase koristi metoda “super()”. Ovaj poziv konstruktora bazične klase mora biti izvršen na samom početku konstruktorske funkcije! (jer on definiše ključnu reč “this”. )
Ukoliko ipak ne pozovemo metodu “super()” u okviru naše konstruktorske funkcije, JavaScript engine će izbaciti error: “Must call super constructor in derived class before accessing ‘this’ or returning from derived constructor”. Error će se javiti čak i ako ne koristimo “this” u našem konstruktoru, kao u narednom primeru:

Znači, ukoliko u novoj klasi imamo konstruktor metodu (čak i da je prazna) “moramo da pozovemo super() metodu”!

OBJAŠNJENJE:
Pozivanjem metode super() izvršavamo ceo kod iz bazične konstruktorske funkcije i definišemo da this ukazuje na novo-generisane objekte.

Šta se dešava ukoliko nova klasa nema definisanu constructor() metodu?

U ovome slučaju JavaScript pravi svoju internu (skrivenu) konstruktorsku funkciju umesto nas, a koja izgleda ovako:

Pristup svojstvu bazične klase

Svojstvu iz bazične klase pristupamo standardno sa “this.svojstvo”:

Pristup metodi bazične klase

Rezervisana reč super predstavlja “roditeljski” konstruktor, stoga kada nam je potreban pristup metodi iz bazične klase, pristupamo mu sa “super.nazivmetode”:


Prototipsko nasledjivanje

Uvod

Prototipsko nasledjivanje (eng. prototypal inheritance) je vrsta nasledjivanja gde objekat nasledjuje svojstva direktno od drugog objekta (ne od nekogo šablona tj. klase). Postoje dva osnovna mehanizma koji omogućavaju prototipsko nasledjivanje:

  1. Prototipsko delegiranje
    Ovaj proces se zasniva se na principu da se svojstva i metode nasledjuju kroz “lanac povezanih prototype objekata” (eng. “prototype chain”).
  2. Concatenative inheritance
    Ovaj proces nasleđivanja svojstava se zasniva na direktnom kopiranju svojstva izvornog objekata. Ovaj mehanizam je prihvaćen i sa standardom ES2015, gde je predstavljen sa “Object.assign()” metodom.

NAPOMENA:
Uokviru standarda ES2015 je predstavljena syntax-a za kreiranje objekata preko klasa, medjutim to je samo estetska promena jer se u pozadini sav posao oko nasledivanja izvršava prema prethodno pomenutom mehanizmu “prototipsko delegiranje”.

Prototipsko delegiranje

Definicija

funkcija objekt

Prototipsko delegiranje je najvažniji mehanizam nasledjivanja objekta u JavaScript-u. Zasniva se na principu da se svojstva i metode nasledjuju kroz “lanac povezanih prototype objekata” (eng. “prototype chain”).
Funkcija Object() je “majka” svih objekata, koja kroz svoj “Object.prototype” objekat prosledjuje svim novo-generisanim objektima neka osnovna svojstva i metode. Više o ovome svojstvu konstruktorke funkcije Object() pročitajte u članku Object() & Object.prototype
Svaki novi objekat ima takodje svoj “prototype” objekat koji je u prvi mah prazan, ali je povezan preko “lanca nasledjivanja” sa roditeljskim objektom, njegovim roditeljskim objektom i tako sve do Object.Prototype objekta. Lanac nasledjivanja je ustvari skup povezanih prototype objekata koji se završava zaključno sa Object.prototype.
Da bi neki objekat mogao da prosledi svom nasledniku metodu, potrebno je da definiše metodu u njegovom prototype objektu, jer je tako pravi dostupnom ostalim objektima koji će da nastanu na osnovu njega.

OBJAŠNJENJE:
Kada JavaScript engine traži neku metodu prvo proverava da li smo je definisali u okviru sopstvenog prototype objekata. Ukoliko ga ne nadje tu, onda ga traži u prototype objektu roditelja. Ali ukoliko ga i tamo ne nadje tražiće dalje duž lanca medjusobno povezanih prototype objekata sve dok ne dodje do poslednjeg u lancu “Objec.prototype”. Ako ga ne nadje ni u njemu izbacuje error.

Zbog čega koristiti prototipsko delegiranje?

Razlog za korišćenje prototipsko delegiranja kao glavnog načina nasledjivanja je dobra optimizacija resursa, a to se najbolje objašnjava kroz poredjenje sa ne-optimizovnim mehanizmom. Prvo ćemo generisati objekte samo na osnovu konstruktorske f-je, koristeći rezervisanu reč new. Tako generisani objekti u sebi dobijaju kopiju svojstava i metoda koji se nalaze u konstruktorskoj funkciji u trenutku generisanja.

Novo generisani objekat (mojAuto) je dobio kopiju svih svojstava. Stoga treba obratiti pažnju na činjenicu da ukoliko nakon generisanja objekta promenimo neko svojstvo u konstruktorskoj funkciji ono neće imati uticaja na instancirani objekat, jer oni nisu povezani:

Loša strana ovoga pristupa izlazi na videlo kada se na osnovu ovakve konstruktorske funkcije instancira veliki broj novih objekata. Razlog za to je činjenica da se pri instanciranju novih objekata u svakom objektu instanciraju i metode, stoga ovakav pristup nepotrebno troši resurse za instanciranje iste metode u svakom objektu.
Za dobijanja optimizovanijeg koda se preporučuje mehanizam “konstruktorska funkcija + prototipsko nasledjivanje”. Kod ovog mehanizma se metode koje su potrebne svim novim objektima definišu u “prototip objektu“. Takve metode smeštene u prototip objekat se instanciraju samo jednom u okviru tog roditeljskog objekta, dok se ostalim objektima (generisanim na osnovu roditeljskog) delegiraju duž lanca nasledjivanja. Svojstva su specifična za svaki objekat stoga njih definišemo u konstruktorskoj funkciji, jer tako svaki novi objekat dobija svoju kopiju sa specifičnim vrednostima.

Nakon generisanja novog objekta (“mojAuto”), njemu je dostupna metoda prikaziPoruku(), koja je instancirana jedino u roditeljskom prototype objektu.

NAPOMENA:
Nasledjivanje putem prototype objekata je “živa stvar”! Ukoliko se naknadno promeni svojstvo u prototype objektu, uticaće na sve generisane objekte koji nasledjuju to svojstvo duž lanca nasledjivanja.

Prototipsko nasledjivanje kroz primer

Princip rada nasledjivanja objekata delegiranjem svojstava ćemo najbolje objasniti kroz primere.

Osnovni objekat:

Krenućemo od jednostavne konstruktorske funkcije Pocetna() i njenog prototype objekta, pa ćemo generisati nove objekte koristeći ključnu reč new():

Konstruktorksa funkcija i njen prototype objekat u JavaScript-u su nešto najbliže što možemo “prići” pojmu klase iz drugih programskih jezika. Novo generisani objekat je pri samom činu stvaranja objekta kopirao sva svojstava iz konstruktorske funkcije (Pocetni()), i povezao svoj prototip objekat sa roditeljskim. Treba naglasiti da naš novi objekat (“pocetni1”), kao i svaki objekat generisan sa ključnom reči “new”, nema svoju konstruktorsku funkciju (nema “Pocetni1()” f-ju), pa njegovo svojstvo .constructor ukazuje na konstruktorsku funkciju Pocetni().

prototype dijagram 1

Ekstendovani objekat:

U narednom delu je opisan postupak kreiranja novog objekta koji ekstenduje funkciju Pocetni():

a) Kreiranje nove konstruktorske funkcije i povezivanje sa svojstvima Pocetni()

Kreiranje modifikovanog “šablon objekta” počinje sa definisanjem nove konstruktorske funkcije:

Da bi nasledili svojstava iz druge konstruktorske funkcije, koristimo metodu call(). Metoda call() omogućava da redefinišemo značenje ključne reči “this”. Nama je potrebno da “this” napisan u konstruktorskoj funkciji “Pocetni()”, ukazuje na novo kreirane objekte nastale korišćenjem funkcije ModifikovaniPocetni(). Stoga za prvi parametar metode (zadužen za redefinisanje “this”) napišemo “this”, jer time definišemo da značenje reči “this” ukazuje na “this” (a to je po korišćenju ključne reči new ustvari novo generisani objekat). Kroz ostale parametre metode call() prosledjujemo dva parametra neophodna za svojstvoPrvo i svojstvoDrugo.

b) Povezivanje prototype objekata sa lancom nasledjivanja

U zavisnosti na koji način želimo da dodelimo metode našem “ModifikovaniPocetni.prototype” objektu, povezivanje prototype objekta se može izvršiti sa:

  1. new()

    Pošto je svaki novo generisani objekat “zakačen” za lanac nasledjivanja, dodeljivanjem novo generisanog objekta našem prototype objektu omogućavamo našem prototype objekatu pristup “lanacu nasledjivanja”.

    Medjutim ovaj način nije preporučen jer njegovim korišćenjem nepotrebno ubacujemo i svojstva iz konstruktorske funkcije (svojstvoPrvo, svojstvoDrugo) u lanac nasledjivanja.

  2. Object.create()

    Ovaj pristup je preporučen, jer pored kreiranja novog objekta, “Object.create()” metoda takodje direktno povezuje dva prototype objekta (prototype objekat novo kreiranog objekta i roditeljski prototip). Ovim povezivanjem za roditeljski prototip, naš novi objekat se “zakačio” za ceo lanac nasledjivanja, pa su mu dostupne sve metode iz njega.

    Medjutim pošto pri ovakvom povezivanju prototype objekata nije korišćena naša konstruktorska funkcija “ModifikovaniPocetni()”, JavaScript engine je ne prepoznaje, pa će potražiti “dublje” duž lanca nasledjivanja, gde je i nalazi kao funkciju “Pocetna()”. Tako da metoda .constructor našeg novog objekta trenutno ukazuje na pogrešan objekat “Pocetni()”. Ovo nije dobro, pa je stoga potrebno da to i promenimo:

c) Dodavanje novih funkcionalnosti

Nakon ekstendovanja našeg novog objekta svojstvima i metodama “roditeljskog” objekta, možemo naš novi objekat “obogatiti” sa novim funkcionalnostima:

Čak možemo da menjamo ekstendovanu metodu, tako što definišemo u našem objektu metodu sa istim imenom koja će da “zakloni” (eng. shadowing) nasledjenu metodu.

Pa tako svi kreirani objekti na osnovu ovog modifikovanog imaju sledeće funkcionalnosti:

prototype dijagram 2

Objedinjeni kod iz primera:


JS snippets u radu sa nizovima

Da li je ulaz niz?

Problem provere tipa podatka se zasniva na činjenici da se pri korišćenju metode toString() niz prebacuje u sledeći string: “[object Array]”.

Prečišćavanje elemenata niza

U sledećem snippet-u je prikazana funkcija koja eliminiše “nepoželjne” članove niza: null, “”, false, undefined i NaN.

Razlike u dva niza

U sledećem snippet-u prikazano rešenje nalazi sve članove niza koji se ne nalaze u oba niza.

Brisanje duplikatnih vrednosti u nizu

a) Niz primitiva

Prebacivanje niza u privremeni objekat (vrednosti niz u ključeve objekta), zatim vršiti iteracije kroz ključeve objekta sa operatorom in:

Ovaj pristup ne održava redosled i ne razlikuje broj od “broj” (1 == “1”)

Ovde se koristi metoda filter() koja uzima callback funkciju kao argument. Callback funkcija testira svaki član niza (prema nekom uslovu), i ako je uslov ispunjen ubacuje (vraća) element u novi niz. Callback funkciji se automatski prosledjuju tri parametra currentValue, index, nizDuplikata.
U našem uslovu se koristi funkcija indexOf() koja pretražuje niz i nalazi index člana niza na osnovu njegove vrednosti. Ukoliko se indeks niza dobijen korišćenjem metode nizDuplikata.indexOf(currentValue) poklapa sa trenutnim indeksom to znači da nije bilo takve vrednosti. Ukoliko postoje dve iste vrednosti u nizu, pri pretrazi sa metodom indexOf() prva vrednost će da “prodje” uslov, dok druga neće jer će vratiti indeks od prve vrednosti, što se neće poklopiti sa trenutnim indeksom.

Set je nova vrsta kolekcije podataka koja se pojavila sa ES6. Glavna karakteristika ove kolekcije je da sadži samo jedinstvene vrednosti u kolekciji.

Postupak:
Prvo se napravi set objekat koji ima jedinstvene vrednosti, zatim se sa for..of iteracijom kroz set objekat napravi niz. Ovaj postupak je mogao da se “skrati” korišćenjem ES6 metode from() koja pravi niz:

b) Niz objekata

Za razliku od primitiva koji se čuvaju prema vrednosti, objekti se čuvaju prema referenci, stoga prethodni pristupi neće dati dobre rezultate.

Za pronalaženje duplikata niza koristićemo metodu filter() koja pravi novi niz od elemenata niza koji su prošli neki test i vratili TRUE. Pri punjenju pomoćnog objekta sa parovima key/value (ključ/vrednost), svaki ključ se konvertuje u string, stoga ne možemo da razlikujemo broj 1 od string-a “1”. Ali korišćenje izraza JSON.stringify(el) nam omogućava da se ipak razlikuju. Ovaj izraz vraća različite vrednosti u zavisnosti od tipa, što se vidi na sledećem primeru:

Spajanje dva niza

Spajanje dva niza (sa duplikatima)

Spajenje dva niza u novi niz sa metodom concat() generiše novi niz. Medjutim ova metoda nije dobra kod velikih nizova jer troši resurse kreiranjem novog niza.

Metoda push() ne generiše novi niz, pa je zbog toga štedljivija po pitanju resursa u odnosu na metodu concat(), pa je ova metoda preporučena u slučaju rada sa velikim nizovima. Medjutim ovaj način ima ogranjičenje, niz koji se dodaje (u ovome slučaju array2) ne može da ima veći broj članova od maksimalnog broj parametara koje funkcija može da primi (Chrome33: 65535, Firefox27:262143, IE11: 131071, Opera12: 1048576).

ili

Napomena: Pogledajte ovde zbog čega se koristi apply() metoda u prethodnim izrazima.

Spajanje dva niza je jednostavno korišćenjem spread opteratora:

Spajanje dva niza (bez duplikata)

Pravljenje klona niza

Ukoliko želimo da napravimo novi niz koji će da zauzme novo mesto u memoriji pri čemu će da sadrži kopiju nekog niza u ovom trenutku, koristićemo sledeći snippet:

Dobijanje poslednjih članova niza

Poslednji članovi niza se dobijaju koristeći metodu slice() ali sa negativnim argumentom -1:

Pronalaženje člana niza prema vrednosti

U sledećem snippet-u se koristi metoda indexOf() koja vraća index traženog elementa koji se nalazi u nizu ili vraća vrednost -1 ako ga niz ne sadrži. Ukoliko se u metodi indexOf() koriste dva atributa onda drugi atribut definiše od kog index-a da se počne pretraga.

Primer

Uklanjanje odredjenog člana niza

Uklanjanje odredjenog člana niza izabranog prema vrednosti člana:

Pražnjenje niza

Kod ovog načina treba obratiti pažnju da se na ovaj način briše sadržaj memorije na koju referenca te promenjive ukazuje, pa ako postoji još neka promenjiva koja ima istu referencu na taj deo memorije i kod nje će doći do izmene.

Ovaj način koristimo ukoliko želimo da obrišemo članove niza ali da ne obrišemo referencu. Izraz “niz=[]” dodeljuje novi prazan niz promenjivoj i ne utiče na druge reference. Treba napomenuti da ovaj način troši memoriju jer je mesto u memoriji gde je čuvan stari niz još uvek zauzeto starim podacima o nizu.

Sortiranja

Sortiranje niza stringova

Sortiranje liste

See the Pen JS sort list by Web programiranje (@chos) on CodePen.


See the Pen Sortiranje liste jQuery by Web programiranje (@chos) on CodePen.


Sortiranje niza brojeva

Metoda sort()je inicijalno namenjena za sortiranje niza stringova, stoga pri sortiranju niza brojeva daje pogrešne rezultate.

Rešenje

Za korišćenje sa brojevima je potrebno dodati funkciju poredjenja.

js sort algoritam

js sort algoritam
js sort algoritam

js sort algoritam

js sort algoritam
js sort algoritam

js sort algoritam

Max i min element niza

Mešanje redosleda elemenata niza

Metoda sort() uzima za parametar callback funkciju koja “funkcija za poredjenje” (ili negativan broj ili nulu ili pozitivan broj), metoda sort() zna koji je broj veći, a koji je manji. Stoga ako “zeznemo” sort() metodu i vraćamo joj slučajne rezultate i ona će da vrati slučajno izmešane brojeve niza.

Ovaj način koristi Fisher–Yates algoritam:

Izvlačenje random člana niza

Prebacivanje niza u listu elemenata

Neke ugradjene funkcije u JavaScript-u npr. Math.max() ne prihvataju niz kao argument već listu. Stoga se javlja potreba da transformišemo niz u listu, a to možemo uraditi na sledeće načine:

Funkcija apply() može da prihvati niz kao argument, pa iako joj to nije glavna namena, često se koristi da “pretvori” niz u listu argumenata. Prvi argument apply() funkcije mora da bude objekat na koji ukazuje this ključna reč (ovo je primarna namena funkcije apply), a drugi je niz koji se prosledjuje callback funkciji kao lista argumenata.

Primer

U sledećem primeru funkcija Math objekta prihvata samo listu argumenata (ne i niz), pa se pre nje koristi apply():

Primer

Metodi push() je potrebno da se prosledjuje lista elemenata u vidu alrgumenata, kao na sledećem primeru:.

Medjutim ako želimo da prosledimo ceo niz, potrebno je da ka prosledimo kao listu, a za to ćemo koristi apply() metodu koja očekuje kao drugi argument listu, pa će implicitno prebaciti niz u listu:

Ovaj način zahteva korišćenje ES6 spread operator-a:


JS snippets u radu sa DOM-om

Uvod

U ovome članku sam pokušao da sakupim JavaScript isečke koda (eng. code snippets), koji mogu biti korisni u svakodnevnom radu sa DOM-om. Skoro svi snippet-i su napisani u dve verzije, koristeći samo plain JavaScript ili uz pomoć jQuery biblioteke.

js iseci koda - code snippets

Document Ready

U sledećim primerima je prikazan “event listener” koji čeka trenutak kada je DOM učitan da bi JavScript mogao sa njim da manipuliše. Isto bi se dobilo kada bi JavaScript kod stavili na kraj body-ja tj. ispred samog zatvarajućeg taga “body”.



Document Load

Dogadjaj load se “okida” tek kad se učita cela stranica sa svim CSS stilovima, slikama



Selektovanje DOM elemenata

Selektovanje preko CSS selektora

HTML

JavaScript
Izbor svih elemenata koji zadovoljavaju selektor

Primer

Izbor samo prvog elementa koji zadovoljava selektor

Ukoliko želimo da sa plain JS vratimo samo prvi element koji zadovoljava kriterijum selektora možemo da koristimo:

Sintaksa za starije browsere

Ukoliko postoji potreba da se zadovolje browseri koji su stariji od IE 11, onda je potrebno da se koriste sledeći JS selektori:

Primer

Selektovanje roditelja

HTML

JavaScript


Selektovanje sve dece

HTML

JavaScript

Naredne naredbe vraćaju niz elemenata sa svom decom izabranog selektora. U nrednim primerima je potrevon selektovati sve li elemente:


NAPOMENA:
Treba naglasiti da “childNodes” vraća kao dete elementa čak i prazan prostor izmedju HTML tagova (kao prazan text node)


Selektovanje prvog deteta

HTML

JavaScript

Ukoliko je želite prvo dete onda mogu da se koriste sledeće naredbe:


NAPOMENA:
Ukoliko postoji prazan prostor izmedju roditeljskog taga i prvog elementa koji mu je dete, neće vratiti taj element nego PRAZAN text node.


Selektovanje poslednjeg deteta

HTML

JavaScript

NAPOMENA:
Ukoliko postoji prazan prostor izmedju roditeljskog taga i poslednjeg elementa koji mu je dete, neće vratiti taj element nego PRAZAN text node.


Selektovanje prethodnog rodjaka

HTML

JavaScript

NAPOMENA:
Ukoliko postoji prazan prostor izmedju roditeljskog taga i poslednjeg elementa koji mu je dete, neće vratiti taj element nego PRAZAN text node.


Selektovanje narednog rodjaka

HTML

JavaScript

NAPOMENA:
Ukoliko postoji prazan prostor izmedju roditeljskog taga i poslednjeg elementa koji mu je dete, neće vratiti taj element nego PRAZAN text node.


Selektovanje svih rodjaka

HTML

JavaScript

U ovom primeru funkcija nadjiRodjake pravi novi niz od dece roditelja koji zadovoljavaju uslov. Dodaje elemente u niz ako ne postoji filter ili ako filter vraća neki element, sve dok postoji sledeći rodjak.

Filtriranje selektovanih elemenata

Redukovanje elemenata koji zadovoljavaju targetirani selektor ukoliko “prodju” test filtera. Test filtera može biti drugi selektor a najčešće je filter funkcija:

HTML

JavaScript