
Objasnění zápisu v JS
Ahoj,
co je prosím tohle za zápis?
var tree = o.i.reduce(function(a,b){
/*
moj kod
*/
}, {});
a proč tohle už nefunguje
var tree = o.i.reduce(function(a,b){
/*
moj kod
*/
});
Děkuji
PS: šlo by to zapsat líp?
Protože ten tvůj kód nejspíš pracuje s počáteční hodnotou (to je ten druhý parametr). A jestli to jde napsat líp se opravdu nedá posoudit, když nevíme, k čemu to má sloužit.
Tady je to celý jestli to pomůže
create-a-nested-list-from-a-object
To je vcelku jednoduché, co se ti na tom nezdá?
Chtěl jsem to všechno dát do class ale tak jak je to napsaný to udělat nejde.
Proč by to nešlo?
Zkoušel jsem to dát celý do objektu abych to trochu odlišil od jiného kódu ale stejně to nefunguje.
No tenhle zápis je nesmysl. Ale psal jsi, že to chceš dát do třídy a teď píšeš o objektu. Asi by sis měl ujasnit, co vlastně chceš.
A proč je to nesmysl, je tam špatná syntaxe nebo to nejde použít v jednom objektu?
Je mi to asi jedno, používat místo tříd objekty které se všechny vytvoří hned při načtení stránky.
Nejde mi ani tak o objekty, moc s nimi neumím pracovat, slouží to spíš jako takový namespace ;)
Funkce jsou jistota ale kilometrové názvy funkcí se fakt nedají používat.
1. Máš tam špatně závorky.
2. Nemůžeš použít this.property pro inicializaci jiné property, protože ta hodnota tam v ten okamžik ještě neexistuje
3. obj.processTree(this.tree, document.getElementById("list"));
this neukazuje na ten tvůj objekt
Takto? Ale závorky jsem nenašel :(
Hned první složená za "items: []" je tam navíc. Proč se tam pořád snažíš protlačit tenhle zápis, když jsem psal, že to takhle nejde?
To s tím tree jsi taky nevylepšil, spíš naopak.
Nejde jako že to nejde ani opravit? Tak to jsem nepochopil. A dát to do jedné class jde, nebo taky ne?
Dát to do jedné třídy to samozřejmě jde. Ale není to zbytečné, když to můžeš dát do jedné funkce?
Do jedené funkce všechno? To jde? To by bylo úplně nejlepší.
Samozřejmě. Proč by to nešlo? JS nedávno ještě třídy vůbec neměl a místo nich se používaly funkce.
A můžeš mi s tím pomoci? Jelikož vůbec nevím jak to myslíš.
Prostě celý ten původní kód obal funkcí.
Nechápu, jako takto?
Třeba tak.
Tak to jsem si tím opravdu pomohl..
A co se ti na tom nezdá?
No netuším jak ty funkce uvnitř volat
Ale ty je nijak volat nepotřebuješ. Zavoláš tu nadřazenou a hotovo.
Tento kód má niekoľko častí:
1. Definovanie dát s položkami priradených do objektu obj.
2. Pripravenie slovníka objDict tak, aby sa dalo jednoducho dostať k položke podľa jej identifikátora. Súčasne sa inicializuje vlastnosť children daných položiek.
3. Naplnenie detí položiek do vlastnosti children. Súčasne sa vyhľadá koreňový uzol (taký, ktorý nemá rodiča; použije sa posledný nájdený; ak sa nenájde, koreňovým uzlom je prázdny objekt).
4. Vytvorenie HTML elementov podľa danej štruktúry.
Ak tomu chceš dať nejakú štruktúru, tak by som nad tým rozmýšľal tak, že v podstate účelom toho kódu je vyrenderovať strom podľa daných dát. Parametrami by mali byť dáta (ktoré chceš zobraziť) a element (do ktorého chceš tie dáta zobraziť).
Z toho mi vychádza, že chceš mať jednu funkciu renderTree(data, ulElement). Takže by som presunul tie var objDict a var tree do funkcie processTree a príslušne upravil zvyšok kódu.
Ak to chceš mať v "mennom priestore", tak tú funkciu zabaľ do objektu, napr. const treeRenderer = { renderTree: function(...) { ... } };
Prípadne ak to chceš mať v triede, tak to zabaľ do triedy: class TreeRenderer { renderTree(...) { ... } }. Voliteľne môžeš deklarovať metódu ako static, ak nechceš vytvárať inštanciu triedy.
Z pohľadu čitateľnosti by stálo za to upraviť kód tak, aby sa nemiešali dve rôzne veci v jednom kroku. T.j. napr. v kroku 2 by mal byť jeden krok vytvorenie mapy a druhý inicializácia children:
- const itemsById = new Map(obj.items.map(item => [item.id, item]));
- obj.items.forEach(item => item.children = []);
Prípadne možno ešte lepšie by bolo vytvoriť si štruktúru vedľa a nemodifikovať dáta. V tom prípade by si mohol inicializovať aj deti v jednom kroku, pretože by to bolo súčasťou jedného logického kroku pre prípravu takejto štruktúry:
- const itemsById = new Map(obj.items.map(item => [item.id, { item, children: [] }]));
Podobne by sa dal upraviť krok 3.
Ďalej by som sa vyhol použitiu var. V súčasnosti je var typicky iba v legacy kóde a namiesto toho sa používa const a let (ak niečo môžeš deklarovať ako const, tak použi const, a let použi iba v ostatných prípadoch).
Viď dokumentácia k reduce: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
Druhý parameter je inicializačná hodnota. Ak žiadnu neposkytneš, použije sa namiesto toho prvý prvok poľa, ktorý sa následne počas redukcie preskočí.
Šlo by to zapísať lepšie tým, že namiesto jednopísmenkových premenných by boli použité normálne názvy premenných. Inak asi ani nie.
Rád bych to měl popsané lépe a nevím co je to za parametr 'c' a 'p' ani nevím co je to za zkratku 'Dict' v tom v názvu.
c - current - současná hodnota
p - previous - předchozí hodnota
dict - dictionary - slovník
Wikan už vysvetlil, tak len doplním popis:
p - previous; predchádzajúca hodnota reduce - pri prvom volaní sa použije inicializačná hodnota, pri ďalších volaniach sa použije akumulovaná hodnota, ktorú vráti reducer.
c - current; aktuálna hodnota, ktorá sa redukuje do akumulovanej hodnoty.
dict - dictionary; slovník, kde v tomto prípade kľúčom je identifikátor uzla a hodnotou je uzol.
Páni, tohle se učí ve škole?
V nějakých určitě. V těch ostatních se to studenti naučí sami.