Symbol
Karakteristike
Symbol je novi tip podataka koji je došao sa ES2015 standardom. Symbol predstavlja jedinstveni token. Simbol se kreira koristeći funkciju Symbol().
1 2 3 |
noviSymbol1 = Symbol(); noviSymbol2 = Symbol(); noviSymbol1 == noviSymbol2; // Vraća false |
Symbol može biti kreiran i sa label-om, koji mu se prosledi kao string. Taj label ne utiče na vrednost symbola, ali je koristan pri debagovanju i može da prikaže koristeći metod toString() nad symbol-om.
1 2 |
let nekiSymbol = Symbol('nekiLabel'); console.log(nekiSimbol); // Vraća: Symbol('nekiLabel') |
Namena: Ključ svojstva objekta
Uglavnom se “symbol” koristi kao ključ svojstva objekta, kada želimo da zaštitimo to svojstvo. Kada se koristi “symbol” kao ključ svojstva objekta, potrebno je da se koriste uglaste zagrade za pristup svojstvu (tzv. “bracket notation”). Takva svojstvo imaju sledeće karakteristike:
- Jedinstveno svojstvo
- Svojstvo ne može da se nabraja (eng. enumerated) kroz “for…in” petlju
- Svosjtvo ignorišu metode: Object.keys(), Object.getOwnPropertyNames() i JSON.stringify()
1 2 3 4 5 6 7 8 9 10 |
let user = {}; let email = Symbol(); user.name = 'Dragoljub'; user.age = 44; Object.keys(user); // Vraća: Array [ "name", "age" ] Object.getOwnPropertyNames(user); // Vraća: Array [ "name", "age" ] JSON.stringify(user); // Vraća: "{"name":"Dragoljub","age":44}" |
Treba napomenuti da privatnost ovoga svojstva nije 100%, jer ipak postoji način za pristup svojstvu preko metoda “.getOwnPropertySymbols()” i .ownKeys():
1 2 |
Object.getOwnPropertySymbols(user); // Vraća: Array [ Symbol() ] Reflect.ownKeys(user) // Vraća: Array [ "name", "age", Symbol() ] |
Map
Karakteristike
Map je kolekcija parova kluč/vrednost (key/value), gde ključ može biti bilo koji tip podataka za razliku od objekta gde ključ može bit ili string ili symbol. Ima ceo set igradjenih metoda za rad sa elementima kolekcije:
- .set() – definisanje novog para
- .delete() – brisanje para
- .get() – dobijanje vrednosti ključa
- .keys() – lista svih ključeva
- .values() – lista svih vrednosti
- .entries() – vraća sve key/value parove u odvojenim nizovima
- .clear() – brisanje sadržaja objekta
Primer
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
var person = new Map(); person.set("ime", "Dragoljub"); person.set("prezime", "Zivanovic"); person.set("posao", "programer"); console.log(person.has("ime")) // true console.log(person.size); // 3 person.delete("posao"); console.log(person.has("posao")); // false console.log(person.size); // 2 var result = person.get("prezime"); console.log(result); // "Zivanovic" console.log(person.keys()); // "ime", "prezime" console.log(person.values()); // "Dragoljub", "Zivanovic" console.log(person.entries()); // ["ime", "Dragoljub"], ["prezime", "Zivanovic"] person.clear(); console.log(person.size); // 0 |
Razlika izmedju objekta i Map
Map je novi objektni podtip koji je veoma sličan objektu ali sa par bitnih razlika:
Objekt | Map |
---|---|
Ključ može biti jedino String ili Symbol. | Map ključ može biti bilo koga tipa, čak i tipa “NaN”. |
Dedeljivanje vrednosti ključu sa = operatorom. | Dodeljivanje vrednosti ključu sa ugradjenim metodama: .set() i .get(). |
Svojstva objekta nisu iterable kolekcija (pa ne može da se koristi forEach() ili for..of metoda za iteraciju kroz svojstva). | Map je iterable kolekcija (pa može da se koristi forEach ili for of za iteraciju kroz elemente) . |
Ne možemo jednostavno dobiti veličinu objekata. | .size svojstvo jednostavno vraća veličinu. |
Ključevi moraju biti jedinstveni inače dobijamo grešku. | Ključevi su ne moraju biti jedinstveni, jer ukoliko se definišu dva člana sa istim ključem, noviji “pregazi” stari |
Za brisanje svojstava mora da se napiše kod. | Map ima ugradjenu metodu .clear() sa kojom jednostavno briše sve. |
If all keys are strings, and you just use get and set, Objects are more performant. | If you focus on iterating, map will be more performant. (TEST) |
Iteracija kroz Map
Za iteraciju kroz parove je dostupna standardna petlja for..of kao i metoda forEach()
1 2 3 4 5 6 7 8 9 10 11 |
var person = new Map(); person.set("ime", "Dragoljub"); person.set("prezime", "Zivanovic"); person.set("posao", "programer"); for (var [key, value] of person) { console.log(key + ' = ' + value); } // Vraća : ime=Dragoljub, prezime=Zivanovic, posao=programer person.forEach((value,key) => console.log(key + ' = ' + value) ) // Vraća : ime=Dragoljub, prezime=Zivanovic, posao=programer |
Konvertovanje objekta u “map”
Možemo da konvertujemo objekat u novi JavaScript tip “map”. Map konstruktor new Map() prihvata kao argumente samo iteratibilne kolekcije, stoga je potrebno da od svojstava objekta kreiramo niz [key, value] parova koristeći metodu “Object.entries(obj)”:
Primer
1 2 3 |
const obj = { foo: 'bar', baz: 42 }; const map = new Map(Object.entries(obj)); console.log(map); // Map { foo: "bar", baz: 42 } |
WeakMap
WeakMap je takodje kolekcija parova kluč/vrednost (key/value), ali upravo “ključ” pravi glavnu razliku izmedju Map i WeakMap. Ključ u slučaju WeakMap-e ne može biti ni jedan drugi tip podataka osim “objekta”. WeakMap ima isti API kao Map: set(), delete( get(), keys(), values(), entries(), clear().
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
wm1.set(o2, 'azerty'); wm2.set(o1, o2); // a value can be anything, including an object or a function wm2.set(o3, undefined); wm2.set(wm1, wm2); // keys and values can be any objects. Even WeakMaps! wm1.get(o2); // "azerty" wm2.get(o2); // undefined, because there is no key for o2 on wm2 wm2.get(o3); // undefined, because that is the set value wm1.has(o2); // true wm2.has(o2); // false wm2.has(o3); // true (even if the value itself is 'undefined') wm3.set(o1, 37); wm3.get(o1); // 37 wm1.has(o1); // true wm1.delete(o1); wm1.has(o1); // false |
Razlika izmedju Map i WeakMap
Map | WeakMap |
---|---|
Ključ može biti bilo koji tip podataka. | Ključ može biti “samo tipa “Object”” (ali ne “null”). |
Map ima metodu za veličinu .size | WeakMap ima metodu za veličinu .length |
Iteracija sa metodom .forEach(). | Kjuč WeakMap tipa nije “enumerable” pa nema metodu za izlistavanje ključeva tj. ne može da se koristi metoda .foreach() za iteraciju. |
Ništa nije “auto destroy”. | Ako se obriše objekat koji je ključ u WeakMap paru, vrednost dodeljena tom ključu će biti takodje obrisana i neće zauzimati memoriju. |
Primer
Ova poslednja razlika je najbitnija, i nju ću detaljno objasniti kroz primer. Posmatraćemo slučaj kada i Map i WeakMap imaju za kluč svojstva objekat
Map i garbage collector
Kod kompajler dodje do linije gde je IIFE i izvrši je nama više nije potrebna promenjiva “a”, ali garbage collector je neće obrisati iz memorije.
1 2 3 4 5 6 |
var nekiMap = new Map(); (function(){ var a = {x: 12}; nekiMap.set(a, "neka vrednost"); })() |
WeakMap i garbage collector
Kod kompajler dodje do linije gde je IIFE i izvrši je nama više nije potrebna promenjiva “b”, pošto je referenca na taj objekat “labava” (eng. weak), garbage collector će obrisati datu promenjivu i osloboditi memoriju.
1 2 3 4 5 6 |
var nekiWeakmap = new WeakMap(); (function(){ var b = {y: 12}; nekiWeakmap.set(b, "neka vrednost"); })() |
Zaključak iz prethodnog primera je da je WeakMap ima bolje iskorišćenje memorije nego kod Map tipa podataka gde može doći do “curenja” memorije (eng. memory leak).
Set
Karakteristike
Set tip podataka je veoma sličan nizovima, stim što ne dozovoljava dupliranje vrednosti. Metode dostupne kroz objekat “Set.prototype” su:
- .add() – dodavanje novog člana
- .delete(value) – brisanje odgovarajućeg člana
- .has(value) – vraća booleanovu vrednost
- .values() – lista svih vrednosti
- .entries() – vraća sve key/value parove u odvojenim nizovima
- .clear() – brisanje sadržaja objekta
- .forEach(callback) – Iteracija kroz objekat
A svojstva:
- .size – ukupan broj parova
- .constructor – vraća funkciju koja je kreirala instancu
Primer
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
var mySet = new Set(); mySet.add(1); // Set { 1 } mySet.add(5); // Set { 1, 5 } // Dodavanje istih vrednosti: mySet.add(5); // Set { 1, 5 } // Dodavanje objekta kao člana: var o = {a: 1, b: 2}; mySet.add(o); mySet.add({a: 1, b: 2}); // Pošto objekat "o" referencira na drugo mesto u memoriji, dodavanje objekta je OK // Set.has(1); // true mySet.has(o); // true // Veličina mySet.size; // 4 //Brisanje člana mySet.delete(5); // Uklanja član 5 |
Razlika izmedju nizova i Set kolekcije
Array | Set |
---|---|
Vrednost elemenata može biti duplirana | Sadrži samo jedinstvene vrednosti |
Fokusiran na index i potrebno je napisati kod da se pronadje odredjeni element i obriše | Fokusiran na vrednost elementa. Vresnost se može veoma lako naći i obrisati. |
Metoda .push() za dodavanje elemenata | Metoda .add() za dodavanje elemenata |
Provera postojanja elementa sa metodom .includes() (ES7) | Provera postojanja elementa sa metodom .has() |
Svojstvo .length se koristi za odredjivanje broja elemenata | Svojstvo .size se koristi za odredjivanje broja elemenata |
Za pražnjenje kolekcije se koristi metoda arr.splice(0,arr.length) | Za pražnjenje kolekcije se koristi metoda mySet.clear() |
Iteracija kroz Set
Iteracija je moguća koristeći petlju for..of:
1 |
for (let item of mySet) console.log(item); |
ili dostupnu metodu forEach():
1 2 3 |
mySet.forEach(function(value) { console.log(value); }); |
Konvertovanje u nizove
Korišćenjem metode “from()” možemo od set objekta napraviti niz:
1 |
var nekiNiz = Array.from(nekiSet); |
Takodje važi i obrnuto:
1 |
noviSet = new Set([1, 2, 3, 4]); |
pa čak i ovo:
1 2 3 4 |
var text = 'Indija'; var mySet = new Set(text); // Set {'I', 'n', 'd', 'i','j', 'a'} mySet.size; // 5 |
WeakSet
WeakSet je specifičan podtip Set tipova podataka jer može samo da sadrži kolekciju objekata.
1 2 3 4 5 6 7 8 9 10 11 12 |
var ws = new WeakSet(); var obj = {}; var foo = {}; ws.add(window); ws.add(obj); ws.has(window); // true ws.has(foo); // false, foo has not been added to the set ws.delete(window); // removes window from the set ws.has(window); // false, window has been removed |
Razlika izmedju Set i WeakSet
Set | WeakSet |
---|---|
Mogu da sadrže bilo koji tip podatak | Mogu da čuvaju samo objekte |
Broj članova kolekcije se dobija koristeći svojstvo .size | Broj članova kolekcije se dobija koristeći svojstvo .length |
Iterabilna kolekcija, može da se koristi .forEach() ili for..of | Nije iterabilna kolekcija i ne može da se koristi .forEach() ili for..of |
Nije auto destroyed | Ako objekat više nema referencu pokupiće ga garbage collector |
Primer
Ova poslednja razlika je najbitnija, i nju ću detaljno objasniti kroz primer. Posmatraćemo slučaj kada i Set i WeakSet imaju za kluč svojstva objekat
Set i garbage collector
Kod kompajler dodje do linije gde je IIFE i izvrši je nama više nije potrebna promenjiva “a”, ali garbage collector je neće obrisati iz memorije.
1 2 3 4 5 6 |
var nekiSet = new Set(); (function(){ var a = {x: 12}; nekiSet.set(a, "neka vrednost"); })() |
WeakSet i garbage collector
Kod kompajler dodje do linije gde je IIFE i izvrši je nama više nije potrebna promenjiva “b”, pošto je referenca na taj objekat “labava” (eng. weak), garbage collector će obrisati datu promenjivu i osloboditi memoriju.
1 2 3 4 5 6 |
var nekiWeakmap = new WeakSet(); (function(){ var b = {y: 12}; nekiWeakmap.set(b, "neka vrednost"); })() |
Zaključak iz prethodnog primera je da je WeakSet ima bolje iskorišćenje memorije nego kod Set tipa podataka gde može doći do “curenja” memorije (eng. memory leak).
Ostavite komentar