JS Savet: Uslovno dodavanje svojstva na objektu

Često se javlja potreba da dodamo neko svojstvo objektu koje zavisi od nekog uslova.

const nickname = req.body.nick;

const formData = {
    name: 'John',
}

if (nickname) {
    formData['nickname'] = nickname;
}

Ovo je najčešći način za dodavanje svojstva objektu. Na ovaj način činimo da kôd bude manje čitljiv i definicija objekta (strukture) se dešava na više mesta.

ES6 u pomoć

Ako iskoristimo pametno "spread" operator možemo značajno da popravimo kôd.

const nickname = req.body.nick;

const formData = {
    name: 'John',
    ...nickname && {nickname: nickname}
}

Ovim smo primetno skratili naš kôd i definicija strukture je na jednom mestu.

Leva strana može da bude bilo koji logički izraz, tako da mogu da se nađu i složeni izrazi. Na primer ako imamo žetone, gde je vrednost može da bude 0 ili neki drugi broj koji je "false". Uslov može ovako da izgleda ...typeof zetoni === "number" && !isNaN(zetoni) && {zetoni},

Kako ovo radi

Prvo da se upoznamo sa && operatorom. Ako zagledamo malo u specifikaciju && operatora, možemo da vidimo da će vrednost biti jedna od vrednosti operatora.

Vrednost koja je rezultat && ne mora da bude boolean tipa.

Ukoliko leva strana nije istinita, desna strana se neće evaluirati i rezultat operacije biće "false". I suprotno, desna strana će se evaluirati samo ako je leva strana istinita. Ovo znači da će naš "spread" operator dobiti levu vrednost false, ili desnu vrednost - objekat.

Kako ovo stvarno radi

Ovo je malo naprednije objašnjenje šta se stvarno dešava i oslanja se na poznavanje ECMA specifikacije. Gore nije objašnjeno šta se desi kada se nađe "number" ili "boolean" vrednost pored "spread" operatora.

Šta može da se nađe sa desne strane "spread" operatora?

  1. null ili undefined
  2. Boolean i Number
  3. Object - Ovo je već poznato ponašanje

Kada pogledamo specifikaciju za "spread" operator vidimo da se pozove CopyDataProperties operator. Gledajući šta radi CopyDataProperties operator, možemo da vidimo da u koraku tri ako se nađe null ili undefined, operator neće uraditi ništa.

const obj = {
    ...null,
    ...undefined
}

console.log(obj) // {}

Ovim smo pokrili prvi slučaj, sada ostaje još drugi slučaj kad se nađu drugi tipovi koji nisu Object.

Ako pogledamo četvrtu stavku CopyDataProperties operatora, vidimo da se nad from (desna strana) zove ToObject. Što znači da će svaki tip biti obmotan u odgovarajući tip objekta. Ono što je bitno da znate je, da ovi objekti, Boolean i Number, sadrže nešto što se zovu interni slotovi. Ovim slotovima ne može da se pristupi već predstavljaju interno stanje objekta na nivou "engine"a. Slotovi u objektu se nazivaju između duplih uglastih zagrada [[imeSlota]].

console.log(new Number(17));
console.log(new Boolean(true));

/*
Number {23}
    __proto__: Number
    [[PrimitiveValue]]: 23
    
Boolean {true}
    __proto__: Boolean
    [[PrimitiveValue]]: true
*/

Primitivnim vrednostima ne možemo obično da pristupimo, već koristimo valueOf().

console.log(new Number(17).valueOf());
console.log(new Boolean(true).valueOf());

/*
    17
    true
*/

Ovo nama ide sve u prilog zato što objekat bez svojstva znači da CopyDataProperties operator nema šta da kopira.

Pokrili smo sve slučajeve, tako da smo sigurni koja god vrednost da dođe kao uslov neće da napravi problem objektu.