Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Функция 'забывает', из какого места она вызвана (https://javascript.ru/forum/misc/53067-funkciya-%27zabyvaet%27-iz-kakogo-mesta-ona-vyzvana.html)

ssadfaf 19.01.2015 16:01

Функция 'забывает', из какого места она вызвана
 
Из одной функции вызываю вторую, которая, при наличии вложений, должна вызывать саму себя с новыми аргументами.
function parseDrawnTreeElems(ContainerParId) {
// бла бла 
for (var i=0; i<window.document.getElementById(ContainerParId).children.length; i++) {
parseDrawnTreeElems(window.document.getElementById(ContainerParId).children[i].id);	
}

Всё работает нормально, пока цикл спускается 'лесенкой' без пропусков по вложениям первой ноды, однако, как только встречается нода без детей и цикл не запускается, она прекращает своё выполнение полностью.
Я предполагал, что она должна вернуться туда, откуда была запущена и продолжить со следуюущей ноды на том уровне, где была вызвана.

Интересно, что аналогичная конструкция с циклом for.. in (по свойствам объектов) у меня работает корректно, а тут я упускаю что-то важное. Киньте хоть ссылку, пожалуйста, а то моего словарного запаса не хватает, чтобы гугл ответил что-нибудь внятное. Такое ощущение, что уже где-то читал об этом, но все мои поисковые запросы ведут в никуда.

danik.js 19.01.2015 16:59

Пошагово выполняй. Ошибок точно в консоль не выпадает?
DOM не изменяешь в процессе работы функции?
Про TreeWalker и NodeIterator слышал?
Зачем в цикле вызываешь функцию getElementById с одним и тем же аргументом?

ssadfaf 20.01.2015 05:54

danik.js,
DOM не меняется.
За TreeWalker и NodeIterator - спасибо огромное, добавил в избранное.
Цитата:

Сообщение от danik.js
Зачем в цикле вызываешь функцию getElementById с одним и тем же аргументом?

Не понял вопрос. Возможно, именно здесь я что-то упускаю?


Цитата:

Сообщение от danik.js
Пошагово выполняй. Ошибок точно в консоль не выпадает?

Ошибок нет, выполняю пошагово, всё увешал консоле.логами и алёртами.
4. По завершении подвызова предыдущий контекст достаётся из стека, выполнение в нём возобновляется.
Собственно, именно такого поведения и ожидаю, но что-то сильно не так с контекстом или чем-то около него.

Вопрос остаётся открытым.

ruslan_mart 20.01.2015 06:24

Так ты получается запускаешь ф-цию, которая пробегается по всем детям элемента и для каждого из них запускает эту же ф-цию, которая опять запускает себя в цикле для каждого ребёнка, и т.д., где логика? Или обьясни, что ты хочешь сделать?

ssadfaf 20.01.2015 08:45

Ruslan_xDD,
Изначальная задумка - да, перебор всех детей у каждого элемента, для поиска последнего ребёнка с заданным параметрами (они хранятся в атрибутах 'data-XXXX'), поэтому lastChild не катит.
Потом я меняю у найденного элемента стили, и эта проверка должна пройти по всем элементам дерева.

Вот я накатал примерчик с массивами, который прекрасно работает, к отличие от моего кода.

function try2RecurseIt() {
  var MyArr = [[1,[2,3],4],[5,6],[7,8,[9,0]]];
  letsDance(MyArr);
}

function letsDance(arr) {
  for (var i=0; i<arr.length; i++) {
    console.log("arr["+i+"] "+ arr[i]);
    if (arr[i].constructor.toString().indexOf("Array") > -1) { // isArray check
      letsDance(arr[i]);
    }
  }
}



Собственно, проблема не связана с изменениями в DOM, она более общая и где-то в другом месте. В основном коде уже убрал все действия, кроме консоле.логов, уже поменял переменную i на gsagdfsa, чтобы она была наверняка уникальной, но всё равно не могу понять, где и почему (и - что) теряет контекст выполнения. Блин.

ssadfaf 20.01.2015 09:10

Всё, вопрос снят. Код был не такой:
function parseDrawnTreeElems(ContainerParId) {
// бла бла 
for (var i=0; i<window.document.getElementById(ContainerParId).children.length; i++) {
parseDrawnTreeElems(window.document.getElementById(ContainerParId).children[i].id);	
}

Собственно, '// бла бла' мне всё и перекосило.
Я, когда готовил вопрос, выкидывал из кода лишнее, вот и выплеснул ребёнка вместе с водой.
Реальный код вместо 'бла-бла' был примерно такой:
function parseDrawnTreeElems(ContainerParId) {
ParId = ContainerParId.slice(9); // (****)

А в вызове внутри функции стояла не переменная ContainerParId, а полученная из неё ParId:
parseDrawnTreeElems(window.document.getElementById(ParId).children[i].id);	
}

И вся фигня происходила от того, что я в строке **** не использовал слово 'var'.
Блин.
Блин.

Блин.

danik.js 20.01.2015 10:54

И все-таки замени все это на TreeWalker, хотя сам не помню как с ним работать.
А вообще - ты неправильный подход выбрал. Наверняка ведь можно сделать так, чтобы не пришлось лазить по всему DOM'у чтобы найти то, что нужно.

ssadfaf 20.01.2015 11:32

danik.js,
да, я глянул TreeWalker на МДН, очень интересная штука, буду иметь ввиду.
Насчёт неправильного подхода - наверняка так и есть, я юзаю то, что знаю, а знаю я пока немного. ))


Часовой пояс GMT +3, время: 04:35.