XPath迭代异常:"尝试使用不可用或不再可用的对象"

A.D*_*.D. 2 javascript xpath dom exception

来自Mozilla的简要改变片段在JavaScript中使用XPath介绍正在抛出异常.

[Exception... "An attempt was made to use an object that is not, or is no longer, usable" code: "11" nsresult: "0x8053000b (InvalidStateError)" location: "debugger eval code Line: 6"]

码:

var headings = document.evaluate('//h2', document, null, XPathResult.ANY_TYPE, null );
var thisHeading = headings.iterateNext();

while (thisHeading) {
  thisHeading.textContent = '\n';
  thisHeading = headings.iterateNext();
}
Run Code Online (Sandbox Code Playgroud)

与原始代码的区别在于我正在改变元素 - 而不仅仅是阅读它们.

为什么我会看到异常以及如何在迭代中更改元素?

A.D*_*.D. 5

我认为这是从xpath和javascript开始时遇到的常见问题,对于那些急于阅读整个介绍/文档的人来说,所以它应该在SO上.


headings.resultType4一个UNORDERED_NODE_ITERATOR_TYPE

当XPath表达式的结果是节点集时,这是默认的返回类型.

你必须知道resultType它是什么,因为:

XPathResult对象允许以3种不同的主要类型返回节点集:

  • 迭代器
  • 快照
  • 第一节点

最重要的信息是:当节点集是其中之一时,您无法更改DOM*_ITERATOR_TYPE.

..如果文档在迭代之间发生变异(文档树被修改),迭代将使迭代失效,并且XPathResult的invalidIteratorState属性设置为true,并抛出NS_ERROR_DOM_INVALID_STATE_ERR异常.

因此,如果您想要更改某些元素,则必须专门请求其中一个快照resultType.您有两种选择:

  • UNORDERED_NODE_SNAPSHOT_TYPE
  • ORDERED_NODE_SNAPSHOT_TYPE

在你的情况下,这是你想要的:

var headings = document.evaluate('//h2', document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null );

for ( var i=0 ; i < headings.snapshotLength; i++ ) {
   headings.snapshotItem(i).textContent = '\n';
}
Run Code Online (Sandbox Code Playgroud)

并注意你正在改变什么:

快照不随文档突变而改变,因此与迭代器不同,快照不会变为无效,但它可能与当前文档不对应,例如节点可能已被移动,可能包含不再存在的节点或新节点可以添加.