Nove metode za rad sa nizovima

Array.from()

Korišćenjem metode “from()” možemo od “array-like” ili “iterable” napraviti niz:

// String u niz
Array.from('foo'); //Vraća: ["f", "o", "o"]

// Set u niz
var s = new Set(['foo', window]);
Array.from(s); // Vraća: ["foo", window]

// Map u niz
var m = new Map([[1, 2], [2, 4], [4, 8]]);
Array.from(m); // Vraća: [[1, 2], [2, 4], [4, 8]]

// Array like u niz
function f() {
  return Array.from(arguments);
}
f(1, 2, 3);  // Vraća: [1, 2, 3]

ES2015

Array.prototype.find()

Ova metoda vraća prvi član niza koji zadovoljava uslov (uslov u okviru callback funkcije). Callback funkciji metoda prosledjuje tri parametra:

  • vrednost člana niza
  • indeks člana niza
  • niz (nad kojim se izvršava metoda)

Pored callback funkcije može (opciono) da se prosledi i argument thisArg, koji definiše na šta će da ukazuje rezervisana reč this u okviru callback funkcije.

izvorniNiz.find(function (currentValue, index, array) {
    //neki uslov
}, [thisArg]);
Primer
var korpa = [
    {imeVoca: 'banana', kolicina: 0},
    {imeVoca: 'jabuka', kolicina: 2},
    {imeVoca: 'visnja', kolicina: 5}
];

function daliImaVoca(vocka) {
    return vocka.kolicina > 0 ;    // Vraca: {imeVoca: 'jabuka', kolicina: 2}
}
var poslastice = korpa.find(daliImaVoca);
console.log("Korpa nije prazna, ima " + poslastice.imeVoca); //  Vraca: Korpa nije prazna, ima jabuka

Metoda findIndex() radi sličnu stvar, stim što umesto prvog elementa koji je zadovoljio uslov, vraća njegov index u nizu.

Continue reading…


“Object literal” poboljšanja

Skraćena notacija za dodeljivanja promenjive

Poznato je da je moguće na osnovu promenjive i njene vrednosti, napraviti svojstva nekog objekta, postupak koji se koristio je bio sledeći:

var a = 'foo',
    b = 42,
    c = {};

var objekat = {
  a: a,
  b: b,
  c: c
};
// objekat.a vraća 'foo' ....

Sada sa novim standardom možemo ovo da skratimo:

var a = 'foo',
    b = 42,
    c = {};

var objekat = {
  a,
  b,
  c
};

ES2015

Skraćena notacija definisanja metoda

Za definisanje metode objekta nije više potrebna ključna reč function i dvotačka. Tako da sada umesto:

osoba= {
 ime: "Pera",
 stampajIme: function() {
   console.log(this.ime);
 }
}

možemo da koristimo skraćenu notaciju:

osoba= {
 ime: "Pera",
 stampajIme() {
   console.log(this.ime);
 }
}

Dozvoljeno korišćenje computed svojstva

Sa novim standardom je dozvoljeno da se za svojstva koriste computed values:

var i = 0;
var a = {
  ['foo' + ++i]: i,
  ['foo' + ++i]: i,
  ['foo' + ++i]: i
};

console.log(a.foo1); // 1
console.log(a.foo2); // 2
console.log(a.foo3); // 3

Pa čak i:

var param = "size";
var config = {
  ['mobile' + param.charAt(0).toUpperCase() + param.slice(1)]: 4
};

console.log(config); // Vraća {mobileSize: 4}

Duplirana svojstva nisu više error

Pre standarda ES2015 je kompajler vraćao grešku ukoliko se duplira svojstvo objekata, sa novim standardom je to sada moguće:

var a = { x: 1, x: 2};

console.log(a.x); // Vraća poslednju vrednost a to je broj 2

Podrazumevane vrednosti parametara funkcije

Uvod

U dosadašnjoj praksi (ES5) se koristio sledeći pristup definisanju podrazumevanih vrednosti parametara funkcje:

function saberi (x, y) {
    x = x || 10;
    y = y || 100;
    console.log(x+y);
}

Problem se javlja kada se prosledi neka vrednost koju kompajler implicitno konvertuje u logičku vrednost “false” (npr. nula), pa zbog toga umesto nje uzima podrazumevanu vrednost:

saberi(0, 50)  // Vraća: 60 

Stoga je potrebno da poboljšamo uslov:

x = (x !== undefined) ? x : 11;

ES2015 sintaksa

Uz novi standard je došla i jednostavnija sintaksa za definisanje podrazumevanih vrednosti sa sledećim pravilom:

Podrazumevano definisana vrednost se primenjuje u slučaju kada je argument izostao ili je nedefinisan, a “null” je validna vrednost!

function test(x = 1) {
  console.log(typeof num);
}

test();          // 'number' (x se definiše kao: 1)
test(undefined); // 'number' (x se definiše kao: 1 too)

test('');        // 'string' (x se definiše kao: '')
test(null);      // 'object' (x se definiše kao: null)

podrazumevani parametri funkcije

Definisanje podrazumevane vrednosti parametra dobro radi i u saradnji sa destruktuiranjem:

function test([x, y] = [1, 2], {z: z} = {z: 3}) {
  return x + y + z;
}

test(); // Vraća: 6

Osim pomenutog izostanka vrednosti ili “undefined”, podrazumevana vrednost može biti bilo šta drugo, pa čak i druga funkcija:

function multiply (a) {
  return a * 2;
}

// Default parameters are also available to later default parameters
function foo (num = 1, duplo = multiply(num)) {
  return [num, duplo];
}
console.log(foo());     // Vraća: [1, 2]
console.log(foo(6));    // Vraća: [6, 12]

let & const

Zajedničke karakteristike

Block scope

Ključne reči let i const ispred promenjive deklariše promenjivu, koja je dostupna jedino u svom lokalnom domenu tzv. “block scope”. Kada se promenjiva deklariše sa let/const u okviru vitičaste zagrade, onda su vitičaste zagrade ivice njenog domena.

if (5 > 0) {
    const osoba = "Pera";
    let godine = 44;
}
console.log(osoba);   // Vraća: ReferenceError: osoba is not defined
console.log(godine);  // Vraća: ReferenceError: godine is not defined 

let & const

Nema hoistovanja promenjive pri kompajliranju

Promenjive deklarisane sa “let/const” se ne hoist-uju na vrh bloka, kao što to rade promenjive deklarisane sa “var”.

function uradi() {
  console.log(bar);   // undefined
  console.log(pi);    // ReferenceError pi is not defined
  console.log(foo);   // ReferenceError  foo is not defined
  var bar = 1;
  const pi = 3.14;
  let foo = 2;
}
uradi();

Ne prave globalne promenjive

Treba napomenuti da ključne reči “let/const” ne prave globalne promenjive čak i kada se nalazi u globalnom domenu:

var x = 'global';
let y = 'nije global';
const z = 'nije global';
console.log(this.x); // "global"
console.log(this.y); // undefined
console.log(this.z); // undefined

Specifičnosti “let” ključne reči

Block scope

Promenjiva može da se deklariše sa ključnom reči “let” i van vitičastih zagrada, pri čemu će ipak pripadi domenu koji prave te vitičaste zagrade. Ovaj izuzetak važi za slučaj kada se promenjiva deklariše u okviru izraza vezanog za iteraciju:

for (let i = 0; i < 5; i++){
    // Domen za promenjivu "i" je izmedju vitičastih zagrada
}
console.log(i); // Vraća: ReferenceError: i is not defined

Redeklarisanje promenjive u istom bloku pravi Syntax Error

Za razliku od deklaracije promenjive sa ključnom reči "var" gde je dozvoljeno ponovno redaklarisanje promenjive, redeklarisanje promenjive u istom domenu sa ključnom "let" nije dozvoljeno, i izbacuje grešku.

if (5>0) {
  let foo;
  let foo = 5; // SyntaxError thrown.
}

Zbog ovoga treba obratiti pažnju da se ne koristi u okviru "switch" izraza jer je sve jedan domen:

let x = 1;
switch(x) {
  case 0:
    let foo = 5;
    break;
  case 1:
    let foo = 10; // SyntaxError for redeclaration.
    break;
}

Ovaj problem može da se prevazidje na sledeći način:

let x = 1;
switch(x) {
  case 0: {
    let foo;
    break;
  }
  case 1: {
    let foo;
    break;
  }
}

Rešava problem iteracije i setTimeout() metode

Korišćenjem ključne reči "let" umesto "var", u okviru "for...petlje", jednostvno rešavamo poznati problem vezan za iteraciju u okviru setTimeout metode.

for (var i = 0; i < 5; i++){
    setTimeout(function(){
        console.log(i);
    }, 1000);
}   // Vraća: 5 5 5 5 5

Pošto ključna reč "let" ponovo definiše novu promenjivu “i” pri svakoj iteraciji petlje, onda se dobija očekivani rezultat:

for (let i = 0; i < 5; i++){
    setTimeout(function(){
        console.log(i);
    }, 1000);
}   // Vraća: 1 2 3 4 5

Više o ovome problemu pogledajte u članku "(Ne)moguće greške u JavaScriptu".

Specifičnost "const" ključne reči

Promenjive deklarisane sa ključnom reči "const" generiše konstantu. Konstante u JavaScriptu su "nepromenljive varijable", tj. varijable kojima se ne može ponovo dodeliti novi sadržaj.

const PI = 3.14;
// Kada zelimo da promenimo konstantu:
PI = 5; // Vraća error  "Assignment to constant variable"

Promenjivost sadržaja konstante!?

Treba napomenuti da nepromenjivost važi samo za promenjivu, ali ne i za nepromenjivost sadržaja konstante!

const nekiObjekat = {
  a : 5,
  b : 6
}
// Kada zelimo da promenimo promenjivu koja je konstanta:
nekiObjekat = 10; // Vraća error "Assignment to constant variable"

// Medjutim bez problema menjamo svojstvo objekta koji je konstanta:
nekiObjekat.a = 8;  // Ne pravi error

ili kao u sledećem primeru dodavanje novih članova nizu neće napraviti grešku:

const people = ['Tesla', 'Musk']
people.push('Berners-Lee')
console.log(people)  //Vraća:  ['Tesla', 'Musk', 'Berners-Lee']

Prava konstanta sa nepromenjivim sadržajem

Ako bi smo hteli da i sadržaj bude nepromenjiv onda je potrebno da koristimo i metodu Object.freeze():

const frozen = Object.freeze(['Ice', 'Icicle', 'Ice cube'])
frozen.push('Water')  // Vraća: Uncaught TypeError: Can't add property 3, object is not extensible

Pogledajte više o "Object.freeze()" u članku "Object() & Object.prototype"


Prikupljanje podataka iz forme sa FormData interfejsom

Uvod

js this

Korišćenje FormData interfejsa prilično olakšava rad sa formama, jer je u stanju da jednostavno pokupi sve vrednosti input-a u formi i sačuva ih u objektu u vidu key/value parova.
Dodatna prednost nad standardnim metodom vezana je za olakšano pisanje serverskog koda. Sa standardnim metodom moramo dodati određeni kod na strani servera koji bi dolazne podatke obradio na specijalizovan način, dok sa FormData to nije potrebno, jer je poslati kod standardizovan i debug-ovan! Treba naglasiti da u formi svi HTML input tag-ovi moraju da imaju atribut ‘name’, jer FormData preko njega ima pristup vrednostima input-a.

Continue reading…


“Async/Await” sintaksa za bolje “Promise”

Uvod

asyn/await

Korišćenje samo jednog promisa je jasno i jednostavno, medjutim kada se program zakomplikuje asinhronom logikom, rad sa promisima se rapidno otežava. Sa ES2017 standardnom je stigla i nova sintaksa “async/await”, koja olakšava rad sa promisima, i omogućava jednostavnije predstavljanje serije asinhronih promisa. Korišćenje “async/await” sintakse nam omogućava da višestruke medjusobno zavisne asinhrone radnje, prikažemo čitljivije i tako izbegnemo tzv. “promise hell”. Treba napomenuti da se uz async funcije ne mogu koristiti “obične” callback funkcije.

“Async/await” sintaksa ne isključuje promise, nego menja način “konzumacije” promisa. Async/Await sintaksa nam omogućava da pišemo asinhroni kod prema sekvencijalnom redosledu izvršavanja tako da liči na sinhroni kod.


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.

Continue reading…


Tipovi podataka u JavaScriptu

Podela tipova podataka

tipovi podataka u javascriptu

U okviru JavaScript-a ima 7 vrsta podataka. Podaci mogu da se podele u dve grupe:
a) Podaci koji čuvaju primitivni tip vrednosti:

  • 1) string
  • 2) number
  • 3) boolean
  • 4) undefined
  • 5) null
  • 6) symbol (ES2015)

b) Podaci koji čuvaju referentni tip vrednosti:

  • 7) objekat
    • array
    • Map (ES2015)
    • WeekMap (ES2015)
    • Set (ES2015)
    • WeekSet (ES2015)

Continue reading…


JS snippets razno (tips & tricks)

Pozajmljivanje metode iz drugog objekta

Metode call, apply i bind se koriste da definišu značenje rezervisane reči this, medjutim to nam takodje omogućava da sa promenom značenja “this” objekat može da “pozajmi” metodu drugog objekata, kao u sledećem primeru:

objekat1 = {
    name:'Pera',
    greet:function(){
        alert('Zdravo, '+this.name)
    }
};
objekat2 = {
    name:'Mika'
};
objekat1.greet.call(objekat2); // Vraca: Zdravo Mika

Čest je slučaj da se pozamljuje neka od metoda Array-a koji su ugradjenih u njegov prototype objekat.

Array.prototype.slice.call (nekiObjekat);

Na ovaj način smo pozajmili Array-ovu metodu slice nekom objektu.

Continue reading…


Simbioza JavaScripta i njegovog okruženja

Uvod

asnhorni JS okruzenje

JavaScript je skriptni jezik, stoga je neophodno da se “smesti” u neki kontejner koji bi mu omogućio rad, taj kontejner se zove JS Runtime Environment (srp. okruženje). Postoje dva tipa okruženja: browser (za rad na klijentu) i node.js (za rad na serveru). Runtime Environment čine :

  1. JS Engine/Runtime
    • Heap
    • Stack
  2. External API
  3. Queue
  4. Event loop

OBJAŠNJENJE:
JavaScript je “single thread” programski jezik i on sam ne može da izvršava više istovremenih paralelnih radnji. Ipak izvršavanje više paralelnih radnji (tzv. asihrono izvršavanje) je moguće uz medjusobnu saradnju JavaScript-a i njegovog okruženja. Više o ovome prolitajte u članku “Princip rada asinhronog JavaScript-a”.

Continue reading…