返回值[
querySelectorAll不是数组,而是NodeList。直到最近才有了
forEach(并且与Javascript的迭代协议兼容,让您将它们用作
for-of和表示法的目标)。
您可以
forEach轻松地填充:
if (typeof NodeList !== "undefined" && NodeList.prototype && !NodeList.prototype.forEach) { // Yes, there's really no need for `Object.defineProperty` here NodeList.prototype.forEach = Array.prototype.forEach;}直接分配在这种情况下细,因为
enumerable,
configurable和
writable都应该
true和它的价值属性。(
enumerable感
true让我感到惊讶,但这是它是如何定义本身在Chrome,火狐,边缘和Safari)。
当
NodeList了
forEach,这也成了 迭代 ,这意味着你可以通过一个内容循环
NodeList通过
for-of回路,并使用
NodeList(在数组初始化比如,在传播符号)在其他地方可迭代的预期。
在实践中,具有使用可迭代性的功能(例如
for-of循环)的浏览器也可能已经提供的这些功能
NodeList,但是要确保(也许您正在转码并包括的polyfill
Symbol),我们需要再做一遍。事情:在其
Symbol.iterator属性中添加一个函数以创建迭代器:
if (typeof Symbol !== "undefined" && Symbol.iterator && typeof NodeList !== "undefined" && NodeList.prototype && !NodeList.prototype[Symbol.iterator]) { Object.defineProperty(NodeList.prototype, Symbol.iterator, { value: Array.prototype[Symbol.itereator], writable: true, configurable: true });}一起做:
if (typeof NodeList !== "undefined" && NodeList.prototype && !NodeList.prototype.forEach) { // Yes, there's really no need for `Object.defineProperty` here NodeList.prototype.forEach = Array.prototype.forEach; if (typeof Symbol !== "undefined" && Symbol.iterator && !NodeList.prototype[Symbol.iterator]) { Object.defineProperty(NodeList.prototype, Symbol.iterator, { value: Array.prototype[Symbol.itereator], writable: true, configurable: true }); }}这是一个同时使用两者的实时示例,请在IE11上尝试此操作(尽管它只会演示
forEach),但它
NodeList本身没有这些功能:
// Using only ES5 features so this runs on IE11function log() { if (typeof console !== "undefined" && console.log) { console.log.apply(console, arguments); }}if (typeof NodeList !== "undefined" && NodeList.prototype) { // forEach if (!NodeList.prototype.forEach) { // Yes, there's really no need for `Object.defineProperty` here console.log("Added forEach"); NodeList.prototype.forEach = Array.prototype.forEach; } // Iterability if (typeof Symbol !== "undefined" && Symbol.iterator && !NodeList.prototype[Symbol.iterator]) { console.log("Added Symbol.iterator"); Object.defineProperty(NodeList.prototype, Symbol.iterator, { value: Array.prototype[Symbol.itereator], writable: true, configurable: true }); }}log("Testing forEach");document.querySelectorAll(".container div").forEach(function(div) { var html = div.innerHTML; div.innerHTML = html[0].toUpperCase() + html.substring(1).toLowerCase();});// Iterableif (typeof Symbol !== "undefined" && Symbol.iterator) { // Using eval here to avoid causing syntax errors on IE11 log("Testing iterability"); eval( 'for (const div of document.querySelectorAll(".container div")) { ' + ' div.style.color = "blue"; ' + '}' );}<div > <div>one</div> <div>two</div> <div>three</div> <div>four</div></div>在
HTMLCollection由归国
getElementsByTagName(以及各种其他旧的API)没有被定义为可迭代的,但如果你喜欢,你也可以做到这一点的
HTMLCollection为好。这是一个执行boty
NodeList(如果需要)和
HTMLCollection(如果需要)的循环:
for (const ctor of [typeof NodeList !== "undefined" && NodeList, typeof HTMLCollection !== "undefined" && HTMLCollection]) { if (ctor && ctor.prototype && !ctor.prototype.forEach) { // (Yes, there's really no need for `Object.defineProperty` here) ctor.prototype.forEach = Array.prototype.forEach; if (typeof Symbol !== "undefined" && Symbol.iterator && !ctor.prototype[Symbol.iterator]) { Object.defineProperty(ctor.prototype, Symbol.iterator, { value: Array.prototype[Symbol.itereator], writable: true, configurable: true }); } }}请注意,这
HTMLCollection是实时的,因此您对DOM进行的更改(影响集合中的内容)会立即反映在集合中,这可能会导致令人惊讶的行为。(
NodeList是一个断开连接的集合,因此不会发生行为。)



