DTree中致命的递归
2010-09-14 13:43:23 来源:WEB开发网其次,细查DTree中的代码,发现很多地方其实都是用递归实现的算法,这也就是为什么我尽管解决了在递归中add节点的问题后还是会不断地出现堆栈溢出的错误。来看看这些导致错误的致命的递归。
1. checkChildreNode方法中的递归在check一个父节点的时候会触发,如果这个父节点下的分支和子节点特别多,即使不引发堆栈溢出的错误,速度估计也很慢。
dTree.prototype.checkChildreNode = function (node, check) {
for (var i = 0; i < node.cNode.length; i++) {
var pCheck = document.getElementById(("c" + this.obj) + node.cNode[i].id);
if (pCheck && !pCheck.disabled) {
pCheck.checked = check;
node.cNode[i].check = check;
}
if (node.cNode[i].cNode.length > 0) {
this.checkChildreNode(node.cNode[i], check);
}
}
};
2. 最致命的地方在这里,render树时会调用addNode方法,而addNode方法又会不断调用node方法,这两个方法之间形成了一个递归调用的过程,如果节点过多,会引发堆栈溢出的错误。这个递归同样会由dtree.tostring()方法引起,它调用addNode,然后addNode调用node,之后node又调用addNode...如此反复,最终形成了罪恶的深渊!
// Creates the node icon, url and text
dTree.prototype.node = function (node, nodeId) {
var str = "<div class="dTreeNode">" + this.indent(node, nodeId);
if (this.config.useIcons) {
if (!node.icon) {
node.icon = (this.root.id == node.pid) ? this.icon.root : ((node._hc) ? this.icon.folder : this.icon.node);
}
if (!node.iconOpen) {
node.iconOpen = (node._hc) ? this.icon.folderOpen : this.icon.node;
}
if (this.root.id == node.pid) {
node.icon = this.icon.root;
node.iconOpen = this.icon.root;
}
if (node.check && node.check != "") {
// onclick='alert(nodeId)'
str += "<input id='c" + this.obj + node.id + "' onclick='javascript: " + this.obj + ".checkNode("" + node.id + "")' type='checkbox' " + (node.check === "true" ? "checked='checked'" : "") + " />";
} else {
str += "<img id="i" + this.obj + nodeId + "" src="" + ((node._io) ? node.iconOpen : node.icon) + "" alt="" />";
}
}
if (node.url) {
str += "<a id="s" + this.obj + nodeId + "" class="" + ((this.config.useSelection) ? ((node._is ? "nodeSel" : "node")) : "node") + "" href="" + node.url + """;
if (node.title) {
str += " title="" + node.title + """;
}
if (node.target) {
str += " target="" + node.target + """;
}
if (this.config.useStatusText) {
str += " onmouseover="window.status='" + node.name + "';return true;" onmouseout="window.status='';return true;" ";
}
if (this.config.useSelection && ((node._hc && this.config.folderLinks) || !node._hc)) {
str += " onclick="javascript: " + this.obj + ".s(" + nodeId + ");"";
}
str += ">";
} else {
if ((!this.config.folderLinks || !node.url) && node._hc && node.pid != this.root.id) {
str += "<a href="javascript: " + this.obj + ".o(" + nodeId + ");" class="node">";
}
}
str += node.name;
if (node.url || ((!this.config.folderLinks || !node.url) && node._hc)) {
str += "</a>";
}
str += "</div>";
if (node._hc) {
str += "<div id="d" + this.obj + nodeId + "" class="clip" style="display:" + ((this.root.id == node.pid || node._io) ? "block" : "none") + ";">";
str += this.addNode(node);
str += "</div>";
}
this.aIndent.pop();
return str;
};
更多精彩
赞助商链接