HTMLCollection和NodeList是否可迭代?

时间:2015-07-08 04:09:42

标签: javascript ecmascript-6 nodelist htmlcollection

在ES6中,iterable是允许for... of的对象,并且具有Symbol.iterator键。

数组是可迭代的,就像集合和地图一样。问题是:HTMLCollectionNodeList是否可以迭代?它们应该是吗?

MDN文档似乎暗示NodeList是可迭代的。

  

for...of循环将在支持for...of的浏览器中正确循环NodeList对象(如Firefox 13及更高版本)

这似乎证实了Firefox的行为。

我在Chrome和Firefox中测试了以下代码,并且惊讶地发现Firefox似乎认为它们是可迭代的,但Chrome却没有。此外,Firefox认为HTMLCollectionNodeList返回的迭代器是同一个。

var col = document.getElementsByClassName('test'); // Should get HTMLCollection of 2 elems
var nod = document.querySelectorAll('.test');      // Should get NodeList of 2 elems
var arr = [].slice.call(col);                      // Should get Array of 2 elems

console.log(col[Symbol.iterator]);    // Firefox: iterator function, Chrome: undefined
console.log(nod[Symbol.iterator]);    // Firefox: iterator function, Chrome: undefined
console.log(arr[Symbol.iterator]);    // Firefox & Chrome: iterator function
console.log(col[Symbol.iterator] === nod[Symbol.iterator]);  // Firefox: true
console.log(col[Symbol.iterator] === arr[Symbol.iterator]);  // Firefox: false
<div class="test">1</div>
<div class="test">2</div>

一个非常奇怪,令人困惑的事情:运行代码片段会产生与复制它并在Firefox中的实际文件/控制台中运行不同的结果(特别是最后的比较)。对这种奇怪的行为的任何启示也将受到赞赏。

4 个答案:

答案 0 :(得分:5)

不幸的是,还没有。但是直到它们为止,你可以像这样容易地填充它们:

HTMLCollection.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];

答案 1 :(得分:4)

Symbol.iteratorNodeListHTMLCollectionDOMTokenListDOMSettableTokenList的支持为discussedadded为{{} 3}}去年。

答案 2 :(得分:2)

正如greiner所指出的那样,2014年WHATWG的DOM规范中添加了对<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> <xsl:strip-space elements="*"/> <xsl:key name="line" match="Line_Info_S4" use="DisplayInvoiceNumber_ID42" /> <xsl:key name="summary" match="Summary_Info_S8" use="DisplayInvoiceNumber_ID39" /> <xsl:key name="remit" match="Remit_To_S11" use="DisplayInvoiceNumber_ID18" /> <xsl:template match="/R5942015"> <xsl:copy> <xsl:apply-templates select="Main___F4211_F42119_S1/Header_S2"/> </xsl:copy> </xsl:template> <xsl:template match="Header_S2"> <Invoices> <InvNumber> <xsl:value-of select="InvoiceNumber_ID62" /> </InvNumber> <!-- more fields here --> <xsl:apply-templates select="key('line', InvoiceNumber_ID62)"/> <xsl:apply-templates select="key('summary', InvoiceNumber_ID62)"/> <xsl:apply-templates select="key('remit', InvoiceNumber_ID62)"/> </Invoices> </xsl:template> <xsl:template match="Line_Info_S4"> <line> <ITEMLineNumber> <xsl:value-of select="AckLineNumber_D_ID1" /> </ITEMLineNumber> <!-- more fields here --> </line> </xsl:template> <xsl:template match="Summary_Info_S8"> <summary> <!-- more fields here --> <AMTGrandTotal> <xsl:value-of select="GrandTotal_T_ID17" /> </AMTGrandTotal> </summary> </xsl:template> <xsl:template match="Remit_To_S11"> <messages> <MSGServiceCharge> <xsl:value-of select="Service_Charge_Message_ID14" /> </MSGServiceCharge> </messages> </xsl:template> </xsl:stylesheet> 的原生Symbol.iterator支持。

不幸的是,Chrome 51是第一个支持它的Chrome版本,它的Beta版本在撰写此答案时才刚刚发布。此外,任何版本的Internet Explorer或Edge都不支持。

要在所有浏览器中为您的代码添加NodeList Symbol.iterator支持,只需使用以下polyfill:

NodeList

答案 3 :(得分:0)

对于任何试图使用TypeScript在NodeList上进行迭代访问的人。我发现此问题与修复https://github.com/microsoft/TypeScript/issues/4947有关,这是您需要的tsconfig.json

{
  "compilerOptions": {
    "lib": ["es2017", "dom", "dom.iterable"],
    "downlevelIteration": true
  }
}

我遇到的问题错误:

Type 'NodeListOf<Element>' is not an array type.

这是触发该问题的代码:

[...document.querySelectorAll('#md-view a')]