2011-06-21 127 views
10

我有一个问题,我有递归的内部for循环:JavaScript的for循环变量和递归

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

显然,因为JavaScript没有块作用域,相同的变量i是越来越修改每次函数叫做。补救这个的最好方法是什么?假设经常使用EcmaScript 3,我不能使用JavaScript 1.7“let”。

我知道这已被问过,但其他问题似乎没有显示递归,它们显示了一个函数调用,其中可以使用闭包。

+2

你能发表一些'node'的示例数据吗? JavaScript将变量作用于包含“函数”或对象字面量的变量,因此每次对'func'的递归调用都应该有它自己的'i'。 – Stoive

+0

同意。在其他情况下进行测试。你可以在jsfiddle.com上发布一些例子吗? –

+1

这个函数看起来像只是循环(递归)了一点(假设节点有孩子)......是否有它应该做的事情? – Gerrat

回答

9

缓存阵列的长度,所以你会有以下内容:

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

您应该总是缓存,尤其是当您处理HTMLCollections时。

1

我认为你的例子应该工作。变量i被声明为本地的,所以当你递归一个新的'我'被使用。

Javascript不会全局和局部变量!

8

只要使用Crockford的walkTheDOM功能:

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

您通过根节点和功能要为每个节点上运行,就像这样:

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

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

现场演示:http://jsfiddle.net/VKWTt/

+0

这只适用于DOM元素,但问题以一般方式提出。 –

+0

@FLekschas它适用于所有类型的节点:https://jsbin.com/daruzo/edit?html,js,console –

+0

好吧,我的措辞是错误的。节点可以是任何东西,不只是一个DOM节点,例如一个普通对象:https://jsbin.com/yepoqixowe/edit?html,js,console –

0

我有点困惑。 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>] 
2

您已经定义的“i”作为范围更广的变量;)

5

了这所面临的问题,像函数的递归过程中的变量值取代得到。递归得到了里面的循环,所以里面的变量对于循环在哪里修改。

使用var来声明在递归修改的变量。

+2

参考链接** [var和not var](http:// stackoverflow.com/questions/1470488/difference-between-using-var-and-not-using-var-in-javascript)**,将会给你更多的见解。 –

+0

优秀的答案。 – Developer

0

这对我有效。

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