我曾多次尝试重构这个以使用迭代而不是递归,但我无法绕过它。也许它与循环中发生的递归有关。协助,甚至只是伪代码,将非常感激。
var getElementAndDescendants = function (el) {
var docFrag = document.createDocumentFragment();
var children = el.parentElement.querySelectorAll("tr[data-parentid='" + el.getAttribute("data-myid") + "']");
docFrag.appendChild(el);
var len = children.length;
for (var index = 0; index < len; index++) {
docFrag.appendChild(getElementAndDescendants(children[index]));
}
return docFrag;
};
更新:这只是一个较大的函数的一小部分,它试图对由在同一个表中有子TR的TR构成的DOM中的伪树进行排序。每个孩子都可以有自己的孩子。解决方案最终成为一个递归函数,其中包含您在此处看到的递归函数。因此,为什么我在微优化之后(如果有的话)。我试图让问题变得简单,从而删除了外部函数。
答案 0 :(得分:3)
就像@Bergi已经说过的那样,从递归到迭代可能不会显着提高性能(或者可能会更慢......得到jsperf!)。抛弃递归的主要原因是当你处理大树时遇到一些堆栈溢出问题。
您绝对应该避免将数据存储在DOM中。
但是,这是我为您创建的深度优先树迭代示例:
var tree = {
title: 'root',
children: [
{ title: 'node 1' },
{
title: 'node 2',
children: [
{ title: 'node 5' },
{ title: 'node 6' }
]
},
{ title: 'node 3' },
{
title: 'node 4',
children: [
{ title: 'node 7' }
]
}
]
};
function dfsIterativePrintTree(node) {
var queue = [node], i, children;
while (node = queue.pop()) {
children = node.children || [];
//loop backward, otherwise the nodes will be traversed backward because
//we pop the nodes.
for (i = children.length; i--;) queue.push(children[i]);
console.log(node.title);
}
}
dfsIterativePrintTree(tree);
答案 1 :(得分:1)
以下内容应该有效,但将其视为伪代码。
function getElementAndDescendants(el) {
/* Keep a last in first out list of elements to "solve." */
var stack = [];
/* Store solutions here. */
solutions = {};
stack.push(el);
while (stack.length != 0) {
var el = stack.pop();
var docFrag = document.createDocumentFragment();
var children = el.parentElement.querySelectorAll("tr[data-parentid='" + el.getAttribute("data-myid") + "']");
var children_len = children.length;
if (!el in solutions && children_len != 0) {
stack.push(el);
/* This way, next time we get to me, we know my children were queued
* up earlier and must have been solved. */
solutions[el] = null;
/* My children are not solved; queue them and solve them first. */
for (var i = 0; i < children_len; ++i) {
stack.push(children[i]);
}
} else {
/* Me and my children are solved! Pull me off the stack and solve. */
stack.pop();
docFrag.appendChild(el);
/* The children must have been solved, if there are any. */
for (var i = 0; i < children_len; ++i) {
docFrag.appendChild(solutions[el]);
}
solutions[el] = docFrag;
}
}
}