Přidat otázku mezi oblíbenéZasílat nové odpovědi e-mailem 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?

Předmět Autor Datum
Protože ten tvůj kód nejspíš pracuje s počáteční hodnotou (to je ten druhý parametr). A jestli to jd…
Wikan 28.12.2019 13:50
Wikan
Tady je to celý jestli to pomůže create-a-nested-list-from-a-object var obj = { items: [{ id: 45,…
Wann 28.12.2019 14:55
Wann
To je vcelku jednoduché, co se ti na tom nezdá?
Wikan 28.12.2019 15:05
Wikan
Chtěl jsem to všechno dát do class ale tak jak je to napsaný to udělat nejde.
Wann 28.12.2019 15:20
Wann
Proč by to nešlo?
Wikan 28.12.2019 15:22
Wikan
Zkoušel jsem to dát celý do objektu abych to trochu odlišil od jiného kódu ale stejně to nefunguje.…
Wann 28.12.2019 15:29
Wann
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…
Wikan 28.12.2019 15:31
Wikan
A proč je to nesmysl, je tam špatná syntaxe nebo to nejde použít v jednom objektu? Je mi to asi jedn…
Wann 28.12.2019 15:39
Wann
1. Máš tam špatně závorky. 2. Nemůžeš použít this.property pro inicializaci jiné property, protože t…
Wikan 28.12.2019 15:54
Wikan
Takto? Ale závorky jsem nenašel :( var obj = { items: [{id: 45,lable: "Test 1.2.1",parent_id: 2}, {…
Wann 28.12.2019 16:07
Wann
Hned první složená za "items: []" je tam navíc. Proč se tam pořád snažíš protlačit tenhle zápis, kdy…
Wikan 28.12.2019 16:14
Wikan
Nejde jako že to nejde ani opravit? Tak to jsem nepochopil. A dát to do jedné class jde, nebo taky n…
Wann 28.12.2019 16:20
Wann
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?
Wikan 28.12.2019 16:24
Wikan
Do jedené funkce všechno? To jde? To by bylo úplně nejlepší.
Wann 28.12.2019 16:29
Wann
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.
Wikan 28.12.2019 16:32
Wikan
A můžeš mi s tím pomoci? Jelikož vůbec nevím jak to myslíš.
Wann 28.12.2019 17:03
Wann
Prostě celý ten původní kód obal funkcí.
Wikan 28.12.2019 17:20
Wikan
Nechápu, jako takto? function MojeFunkce () { var obj = { items: [{ id: 45, lable: "Test 1.2.1", p…
Wann 28.12.2019 17:57
Wann
Třeba tak.
Wikan 28.12.2019 18:40
Wikan
Tak to jsem si tím opravdu pomohl..
Wann 28.12.2019 20:25
Wann
A co se ti na tom nezdá?
Wikan 28.12.2019 20:31
Wikan
No netuším jak ty funkce uvnitř volat :-D
Wann 28.12.2019 20:50
Wann
Ale ty je nijak volat nepotřebuješ. Zavoláš tu nadřazenou a hotovo.
Wikan 28.12.2019 20:51
Wikan
Tento kód má niekoľko častí: 1. Definovanie dát s položkami priradených do objektu obj. 2. Priprave… poslední
moose 29.12.2019 14:37
moose
Viď dokumentácia k reduce: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_…
moose 28.12.2019 15:11
moose
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 'D…
Wann 28.12.2019 15:23
Wann
c - current - současná hodnota p - previous - předchozí hodnota dict - dictionary - slovník
Wikan 28.12.2019 15:26
Wikan
Wikan už vysvetlil, tak len doplním popis: p - previous; predchádzajúca hodnota reduce - pri prvom…
moose 28.12.2019 15:29
moose
Páni, tohle se učí ve škole?
Wann 28.12.2019 15:46
Wann
V nějakých určitě. V těch ostatních se to studenti naučí sami.
Wikan 28.12.2019 15:56
Wikan

Tady je to celý jestli to pomůže

create-a-nested-list-from-a-object

var obj = {
  items: [{
    id: 45,
    lable: "Test 1.2.1",
    parent_id: 2
  }, {
    id: 12,
    lable: "Test 1.0",
    parent_id: 0
  }, {
    id: 32,
    lable: "Test 1.1",
    parent_id: 12
  }, {
    id: 2,
    lable: "Test 1.2",
    parent_id: 12
  }]
}

var objDict = obj.items.reduce(function(p, c) {
  p[c.id] = c;
  c.children = [];
  return p;
}, {});

var tree = obj.items.reduce(function(p, c) {
  if (!c.parent_id) {
    p = c;
  } else {
    objDict[c.parent_id].children.push(c);
  }
  return p;
}, {});

processTree(tree, document.getElementById("list"));

function processTree(node, element) {
  var li = document.createElement('li');
  li.innerText = node.lable;
  element.appendChild(li);
  if (node.children.length) {
    var ul = document.createElement('ul');
    li.appendChild(ul);
    for (var i = 0; i < node.children.length; i++) {
      processTree(node.children[i], ul);
    }
  }
}

Zkoušel jsem to dát celý do objektu abych to trochu odlišil od jiného kódu ale stejně to nefunguje.


var obj = {
        items: [{
          id: 45,
          lable: "Test 1.2.1",
          parent_id: 2
        }, {
          id: 12,
          lable: "Test 1.0",
          parent_id: 0
        }, {
          id: 32,
          lable: "Test 1.1",
          parent_id: 12
        }, {
          id: 2,
          lable: "Test 1.2",
          parent_id: 12
        }]
      },
      
      objDict : this.items.reduce(function(p, c) {
        p[c.id] = c;
        c.children = [];
        return p;
      }, {}),
      
      tree : this.items.reduce(function(p, c) {
        if (!c.parent_id) {
          p = c;
        } else {
          this.objDict[c.parent_id].children.push(c);
        }
        return p;
      }, {}),
      
      processTree : function (node, element) {
        var li = document.createElement('li');
        li.innerText = node.lable;
        element.appendChild(li);
        if (node.children.length) {
          var ul = document.createElement('ul');
          li.appendChild(ul);
          for (var i = 0; i < node.children.length; i++) {
            this.processTree(node.children[i], ul);
          }
        }
      }

obj.processTree(this.tree, document.getElementById("list"));

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.

Takto? Ale závorky jsem nenašel :(

var obj = {
        items: [{id: 45,lable: "Test 1.2.1",parent_id: 2}, {
                 id: 12,lable: "Test 1.0",parent_id: 0}, {
                 id: 32,lable: "Test 1.1",parent_id: 12}, {
                 id: 2,lable: "Test 1.2",parent_id: 12}]
      },

      objDict : items.reduce(function(p, c) {
        p[c.id] = c;
        c.children = [];
        return p;
      }, {}),

      tree : items.reduce(function(p, c) {
        if (!c.parent_id) {
          p = c;
        } else {
          this.objDict[c.parent_id].children.push(c);
        }
        return p;
      }, {}),

      processTree : function (node, element) {
        var li = document.createElement('li');
        li.innerText = node.lable;
        element.appendChild(li);
        if (node.children.length) {
          var ul = document.createElement('ul');
          li.appendChild(ul);
          for (var i = 0; i < node.children.length; i++) {
            this.processTree(node.children[i], ul);
          }
        }
      }

obj.processTree(tree, document.getElementById("list"));

Nechápu, jako takto?


function MojeFunkce ()
{
var obj = {
  items: [{
    id: 45,
    lable: "Test 1.2.1",
    parent_id: 2
  }, {
    id: 12,
    lable: "Test 1.0",
    parent_id: 0
  }, {
    id: 32,
    lable: "Test 1.1",
    parent_id: 12
  }, {
    id: 2,
    lable: "Test 1.2",
    parent_id: 12
  }]
}

var objDict = obj.items.reduce(function(p, c) {
  p[c.id] = c;
  c.children = [];
  return p;
}, {});

var tree = obj.items.reduce(function(p, c) {
  if (!c.parent_id) {
    p = c;
  } else {
    objDict[c.parent_id].children.push(c);
  }
  return p;
}, {});

processTree(tree, document.getElementById("list"));

function processTree(node, element) {
  var li = document.createElement('li');
  li.innerText = node.lable;
  element.appendChild(li);
  if (node.children.length) {
    var ul = document.createElement('ul');
    li.appendChild(ul);
    for (var i = 0; i < node.children.length; i++) {
      processTree(node.children[i], ul);
    }
  }
}
}

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.

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.

Zpět do poradny Odpovědět na původní otázku Nahoru