Aktualizacja :
Przedstawiłem kilka podstawowych testów wydajności dla każdej z tych 6 metod na 1000 uruchomień. getElementsByTagName
jest najszybszy, ale wykonuje półdupą robotę, ponieważ nie wybiera wszystkich elementów, a tylko jeden określony typ tagu (tak mi się wydaje p
) i ślepo zakłada, że jego firstChild jest elementem tekstowym. Może być trochę wadliwy, ale służy do celów demonstracyjnych i porównania jego wydajności z TreeWalker
. Przeprowadź testy na jsfiddle, aby zobaczyć wyniki.
- Korzystanie z TreeWalker
- Niestandardowe przemierzanie iteracyjne
- Niestandardowe przemierzanie rekurencyjne
- Zapytanie XPath
- querySelectorAll
- getElementsByTagName
Załóżmy na chwilę, że istnieje metoda, która pozwala na Text
natywne pobranie wszystkich węzłów. Nadal musiałbyś przejść przez każdy wynikowy węzeł tekstowy i wywołać, node.nodeValue
aby uzyskać rzeczywisty tekst, tak jak w przypadku każdego węzła DOM. Zatem kwestia wydajności nie polega na iterowaniu przez węzły tekstowe, ale na iterowaniu przez wszystkie węzły, które nie są tekstowe i sprawdzaniu ich typu. Twierdziłbym (na podstawie wyników), że TreeWalker
działa tak samo szybko getElementsByTagName
, jeśli nie szybciej (nawet z handicapped getElementsByTagName).
Uruchomiono każdy test 1000 razy.
Metoda Suma ms Średnia ms
--------------------------------------------------
document.TreeWalker 301 0,301
Iteracyjny Traverser 769 0,769
Rekurencyjny Traverser 7352 7.352
Zapytanie XPath 1849 1,849
querySelectorAll 1725 1.725.0
getElementsByTagName 212 0.212
Źródło dla każdej metody:
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);
}
}
Rekurencyjne przechodzenie po drzewie
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);
}
Iteracyjne przechodzenie po drzewie
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 (handicap)
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);
}
}
Również ta dyskusja może być pomocna - http://bytes.com/topic/javascript/answers/153239-how-do-i-get-elements-text-node