Actualización :
He descrito algunas pruebas de rendimiento básicas para cada uno de estos 6 métodos en 1000 ejecuciones. getElementsByTagName
es el más rápido, pero hace un trabajo a medias, ya que no selecciona todos los elementos, sino solo un tipo particular de etiqueta (creo p
) y asume ciegamente que su firstChild es un elemento de texto. Puede que tenga algunos defectos, pero está ahí para fines de demostración y para comparar su rendimiento con TreeWalker
. Ejecute las pruebas usted mismo en jsfiddle para ver los resultados.
- Usando un TreeWalker
- Recorrido iterativo personalizado
- Recorrido recursivo personalizado
- Consulta de XPath
- querySelectorAll
- getElementsByTagName
Supongamos por un momento que existe un método que le permite obtener todos los Text
nodos de forma nativa. Aún tendría que atravesar cada nodo de texto resultante y llamar node.nodeValue
para obtener el texto real como lo haría con cualquier nodo DOM. Entonces, el problema del rendimiento no es iterar a través de los nodos de texto, sino a través de todos los nodos que no son texto y verificar su tipo. Yo diría (basado en los resultados) que TreeWalker
funciona tan rápido como getElementsByTagName
, si no más rápido (incluso con getElementsByTagName jugando con discapacidad).
Realicé cada prueba 1000 veces.
Método Total ms Promedio ms
--------------------------------------------------
document.TreeWalker 301 0.301
Recorrido iterativo 769 0,769
Traverser recursivo 7352 7.352
Consulta XPath 1849 1.849
querySelectorAll 1725 1.725
getElementsByTagName 212 0.212
Fuente para cada método:
TreeWalker
function nativeTreeWalker() {
var walker = document.createTreeWalker(
document.body,
NodeFilter.SHOW_TEXT,
null,
false
);
var node;
var textNodes = [];
while(node = walker.nextNode()) {
textNodes.push(node.nodeValue);
}
}
Recorrido de árbol recursivo
function customRecursiveTreeWalker() {
var result = [];
(function findTextNodes(current) {
for(var i = 0; i < current.childNodes.length; i++) {
var child = current.childNodes[i];
if(child.nodeType == 3) {
result.push(child.nodeValue);
}
else {
findTextNodes(child);
}
}
})(document.body);
}
Recorrido iterativo del árbol
function customIterativeTreeWalker() {
var result = [];
var root = document.body;
var node = root.childNodes[0];
while(node != null) {
if(node.nodeType == 3) {
result.push(node.nodeValue);
}
if(node.hasChildNodes()) {
node = node.firstChild;
}
else {
while(node.nextSibling == null && node != root) {
node = node.parentNode;
}
node = node.nextSibling;
}
}
}
querySelectorAll
function nativeSelector() {
var elements = document.querySelectorAll("body, body *");
var results = [];
var child;
for(var i = 0; i < elements.length; i++) {
child = elements[i].childNodes[0];
if(elements[i].hasChildNodes() && child.nodeType == 3) {
results.push(child.nodeValue);
}
}
}
getElementsByTagName (desventaja)
function getElementsByTagName() {
var elements = document.getElementsByTagName("p");
var results = [];
for(var i = 0; i < elements.length; i++) {
results.push(elements[i].childNodes[0].nodeValue);
}
}
XPath
function xpathSelector() {
var xpathResult = document.evaluate(
"//*/text()",
document,
null,
XPathResult.ORDERED_NODE_ITERATOR_TYPE,
null
);
var results = [], res;
while(res = xpathResult.iterateNext()) {
results.push(res.nodeValue);
}
}
Además, puede encontrar útil esta discusión: http://bytes.com/topic/javascript/answers/153239-how-do-i-get-elements-text-node