Javascript для переменной цикла и рекурсии

У меня проблема, когда у меня есть рекурсия внутри цикла for:

function func(node) {
    for(var i = 0; i < node.children.length; i++) {
       func(node.children[i]);
    } 
} 

Очевидно, что, поскольку JavaScript не имеет области блока, одна и та же переменная я изменяется каждый раз, когда вызывается функция. Каков наилучший способ исправить это? Предположим, что обычный EcmaScript 3 и я не могу использовать JavaScript 1.7 "let".

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

Ответ 1

Загрузите длину массива так, чтобы у вас было следующее:

function recurse(node) {
    for(var i = 0, count = node.children.length; i < count; i++) {
        recurse(node.children[i]);
    }
} 

Вы всегда должны кэшировать, особенно когда имеете дело с HTMLCollections.

Ответ 2

Просто используйте функцию Crockford walkTheDOM:

function walkTheDOM(node, func) {
    func(node);
    node = node.firstChild;
    while (node) {
        walkTheDOM(node, func);
        node = node.nextSibling;
    }
}

Вы передаете root node и функцию, которую вы хотите запустить для каждого node, например:

var root = document.getElementById('wrap');

walkTheDOM(root, function(node) {
    console.log( node.nodeName );
});

Live demo: http://jsfiddle.net/VKWTt/

Ответ 3

Была ли эта проблема проблемой, например, во время рекурсии функции значения переменных были заменены. рекурсия была внутри цикла для, поэтому переменные внутри цикла для, где были изменены.

Используйте var, чтобы объявить переменные, которые были изменены при рекурсии.

Ответ 4

Вы уже определили "i" как переменную в более широкой области;)

Ответ 5

Я думаю, что вы, например, должны работать. Переменная i объявлена ​​локальной, поэтому, когда вы рекурсируете использовать новый "i".

Javascript выполняет глобальные и локальные переменные!

Ответ 6

Я немного смущен. i объявляется локально и поэтому не изменяется одна и та же переменная i. Протестировано на этой самой странице:

var span = document.getElementsByTagName("span")[0];
function func(node) {
    for(var i = 0; i < node.children.length; i++) {
       console.log([i, node]);
       func(node.children[i]);
    } 
}
func(span);

// returns
// [0, <span id="hlinks-user">...</span>]
// [1, <span id="hlinks-user">...</span>]
// [2, <span id="hlinks-user">...</span>]
// [0, <a href="/users...">...</a>]
// [3, <span id="hlinks-user">...</span>]
// [0, <span title="1 silver...">...</span>]
// [1, <span title="1 silver...">...</span>]
// [4, <span id="hlinks-user">...</span>]
// [0, <span title="7 bronze...">...</span>]
// [1, <span title="7 bronze...">...</span>]
// [5, <span id="hlinks-user">...</span>]

Ответ 7

Это сработало для меня.

 function DragDropChanges(nodeChanged) {
        if (nodeChanged.children != null) {
            for (i = 0; i < nodeChanged.children.length;
                var temp = i;
                DragDropChanges(nodeChanged.children[i]);
                i = temp;
            }
        }
    }