Преобразование ТАБЛИЦЫ с родителями в json объекты
Приветствую, стоит задача передать в ext js Tree json с дочерними элементами из БД. Есть такой код, который задачу выполняет, но я не пойму как он работает, прошу знающих людей объяснить что происходит
в массив O один раз присваивается объект, затем работа идет с объектом temp, как происходит так, что в массиве O под конец выполнения функции находится вся структура? var _makeTree = function(options) { var children, e, id, o, pid, temp, _i, _len, _ref; id = options.id || "id"; pid = options.parentid || "parentid"; children = options.children || "children"; temp = {}; o = []; _ref = options.q; for (_i = 0, _len = _ref.length; _i < _len; _i++) { //console.log(_i); e = _ref[_i]; //console.log(e); e[children] = []; temp[e[id]] = e; if (temp[e[pid]] != null) { temp[e[pid]][children].push(e); } else { //console.log('o.push(e);'); o.push(e); } } return o; }; var test =_makeTree({ q: [ {"id": 123, "parentid": 0, "name": "Mammals"}, {"id": 456, "parentid": 123, "name": "Dogs"}, {"id": 214, "parentid": 456, "name": "Labradors"}, {"id": 810, "parentid": 456, "name": "Pugs"}, {"id": 919, "parentid": 456, "name": "Terriers"} ] }); console.log(test); /* [{"id":123,"parentid":0,"name":"Mammals","children": [{"id":456,"parentid":123,"name":"Dogs","children":[{"id":214,"parentid":456,"name":"Labradors","children":[]},{"id":810,"parentid":456,"name":"Pugs","children":[]},{"id":919,"parentid":456,"name":"Terriers","children":[]}]}]}] */ |
Код писал сумрачный гений, который считает названия типа _i, _len, o само собой разумеющимися. Перевожу телепатически:
function _makeTree(options) { var id = options.id || "id"; var parentid = options.parentid || "parentid"; var children = options.children || "children"; var itemsById = {}; var result = []; var stack = options.q; for (var i = 0, l = stack.length; i < l; i++) { var item = stack[i]; item[children] = []; itemsById[item[id]] = item; if (itemsById[item[parentid]] != null) { itemsById[item[parentid]][children].push(item); } else { result.push(item); } } return result; } Небольшую неясность вносит также то, что во входящей структуре q и в результате в качестве имен свойств 'id', 'parentid' и 'children' можно использовать произвольные строки, переданные в options. Это местами превращает код в череду вложенных квадратных скобок вместо нормальных обращений к свойствам. |
Кстати, код ломается на несортированном массиве. Т.е. вот такой вызов отдает уже не дерево:
var test =_makeTree({ q: [ {"id": 456, "parentid": 123, "name": "Dogs"}, {"id": 123, "parentid": 0, "name": "Mammals"}, ] }); |
Я наверно не понимаю элементарных вещей, но почему result в итоге содержит всю структуру(при отсортированном массиве)? мы один раз помещаем в него элемент item, при первом проходе цикла, как вся остальная структура children заполняется? подразумеваю что дело в ссылках на объект.
|
Да. На первом шаге итерации Mammals добавляется в itemsById. В itemsById ищется родитель для Mammals, но т.к. в itemsById пока что есть только Mammals, а элемента с id == 0 вообще нет в исходном наборе, то срабатывает else и Mammals попадает в result. На втором шаге все повторяется до проверки. Для Dogs в itemsById находится родитель — это Mammals. Далее в Mammals.children пушится Dogs. Цикл повторяется.
Объекты в js передаются только по ссылке. И когда в цикле в первый раз делается itemsById[item[parentid]][children].push(item), это эквивалентно result[0][children].push(item), потому что и result[0] и itemsById[item[parentid]] ссылаются на Mammals. |
ixth,
Благодарю за помощь :) |
Часовой пояс GMT +3, время: 15:03. |