getElementsByTagName()相当于textNodes

有没有办法获得文档中的所有textNode对象的集合?

getElementsByTagName()适用于元素,但textNode不是元素。

更新:我意识到这可以通过步行的DOM – 如下面的build议。 我知道如何编写一个DOM-walker函数来查看文档中的每个节点。 我希望有一些浏览器本地的方式来做到这一点。 毕竟有一点奇怪,我可以通过一个内置的调用来获得所有的<input> ,但不是所有的textNode

更新

我已经概述了1000种运行的6种方法的基本性能testing。 getElementsByTagName是最快的,但它做了一半的工作,因为它不select所有的元素,但只有一个特定types的标签(我认为是p ),并盲目地认为它的firstChild是一个文本元素。 它可能没有什么缺陷,但它有示范的目的,并将其性能与TreeWalker进行比较。 在jsfiddle上自己运行testing来查看结果。

  1. 使用TreeWalker
  2. 自定义迭代遍历
  3. 自定义recursion遍历
  4. Xpath查询
  5. querySelectorAll
  6. 的getElementsByTagName

让我们暂时假定有一种方法可以让你本地获得所有的Text节点。 您仍然必须遍历每个生成的文本节点,并调用node.nodeValue来获取实际的文本,就像使用任何DOM节点一样。 因此,性能问题不是遍历文本节点,而是遍历所有不是文本的节点并检查其types。 我会争辩(基于结果), TreeWalker执行速度与getElementsByTagName一样快,如果不是更快(即使getElementsByTagName正在播放残疾人)。

每次testing1000次。

方法总计毫秒平均毫秒
 --------------------------------------------------
文件.TreeWalker 301 0.301
迭代遍历769 0.769
recursion遍历器7352 7.352
 XPath查询1849 1.849
 querySelectorAll 1725 1.725
 getElementsByTagName 212 0.212

每种方法的来源:

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); } } 

recursion树遍历

 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); } 

迭代树遍历

 function customIterativeTreeWalker() { var result = []; var root = document.body; var node = root.childNodes[0]; while(node != null) { if(node.nodeType == 3) { /* Fixed a bug here. Thanks @theazureshadow */ 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 *"); /* Fixed a bug here. Thanks @theazureshadow */ 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 (让分)

 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); /* Fixed a bug here. Thanks @theazureshadow */ } } 

此外,您可能会发现这个讨论有帮助 – http://bytes.com/topic/javascript/answers/153239-how-do-i-get-elements-text-node

我知道你特别要求collections,但是如果你只是非正式的意思,并不在乎是否所有的东西都加在一起,你可以使用:

 var allTextAsString = document.documentElement.textContent || document.documentElement.innerText; 

第一个项目是DOM3标准方法。 但是请注意, innerText似乎在支持它的实现(至lessIE和Chrome)中排除脚本或样式标记内容,而textContent包含它们(在Firefox和Chrome中)。

  document.deepText= function(hoo, fun){ var A= [], tem; if(hoo){ hoo= hoo.firstChild; while(hoo!= null){ if(hoo.nodeType== 3){ if(typeof fun== 'function'){ tem= fun(hoo); if(tem!= undefined) A[A.length]= tem; } else A[A.length]= hoo; } else A= A.concat(document.deepText(hoo, fun)); hoo= hoo.nextSibling; } } return A; } 

/ *您可以返回某个父元素的所有后代文本节点的数组,或者您可以将其传递给某个函数,并在文本中执行某些操作(查找,replace或其他)。

此示例返回正文中非空白文本节点的文本:

 var A= document.deepText(document.body, function(t){ var tem= t.data; return /\S/.test(tem)? tem: undefined; }); alert(A.join('\n')) 

* /

方便search和replace,突出显示等

 var el1 = document.childNodes[0] function get(node,ob) { ob = ob || {}; if(node.childElementCount) { ob[node.nodeName] = {} ob[node.nodeName]["text"] = []; for(var x = 0; x < node.childNodes.length;x++) { if(node.childNodes[x].nodeType == 3) { var txt = node.childNodes[x].nodeValue; ob[node.nodeName]["text"].push(txt) continue } get(node.childNodes[x],ob[node.nodeName]) }; } else { ob[node.nodeName] = (node.childNodes[0] == undefined ? null :node.childNodes[0].nodeValue ) } return ob } var o = get(el1) console.log(o) 

下面是最快的TreeWalker方法的一个现代Iterator版本:

 function getTextNodesIterator(el) { const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT); const next = () => { const value = walker.nextNode(); return { value, done: !value }; }; walker[Symbol.iterator] = () => ({next}); return walker; } 

用法:

 const textNodes = [...getTextNodesIterator(document.body)]; 

或者更有趣的是,用for-of循环:

 for (const textNode of getTextNodesIterator(document.body)) { console.log(textNode) }