这是一个使用我之前编写的 treeWalk 函数的实现,然后将其包装在一个 jquery 方法中,该方法在传入的 jQuery 对象中查找每个项目的最深后代,并返回一个包含这些节点的新 jQuery 对象。
递归和大量 jQuery 的解决方案可以用更少的代码完成,但它可能会更慢。这是基于遍历树的通用原生 JS 树遍历函数。
使用比 OP 的 HTML 更复杂的 HTML 测试用例的工作演示:http: //jsfiddle.net/jfriend00/8tC3a/
$.fn.findDeepest = function() {
var results = [];
this.each(function() {
var deepLevel = 0;
var deepNode = this;
treeWalkFast(this, function(node, level) {
if (level > deepLevel) {
deepLevel = level;
deepNode = node;
}
});
results.push(deepNode);
});
return this.pushStack(results);
};
var treeWalkFast = (function() {
// create closure for constants
var skipTags = {"SCRIPT": true, "IFRAME": true, "OBJECT": true, "EMBED": true};
return function(parent, fn, allNodes) {
var node = parent.firstChild, nextNode;
var level = 1;
while (node && node != parent) {
if (allNodes || node.nodeType === 1) {
if (fn(node, level) === false) {
return(false);
}
}
// if it's an element &&
// has children &&
// has a tagname && is not in the skipTags list
// then, we can enumerate children
if (node.nodeType === 1 && node.firstChild && !(node.tagName && skipTags[node.tagName])) {
node = node.firstChild;
++level;
} else if (node.nextSibling) {
node = node.nextSibling;
} else {
// no child and no nextsibling
// find parent that has a nextSibling
--level;
while ((node = node.parentNode) != parent) {
if (node.nextSibling) {
node = node.nextSibling;
break;
}
--level;
}
}
}
}
})();
var deeps = $(".start").findDeepest();
deeps.each(function(i,v){
$("#results").append(
$("<li>").html($(v).prop("tagName") + " " + $(v).html())
);
});