我正在编写用于选择产品(颜色等)的脚本,该脚本可在除 Internet Explorer (11)和 Edge 之外的所有浏览器中使用。
我将每个参数的选择放入数组中,并使用方法将函数应用于它们array.forEach()。
array.forEach()
color参数的示例:
var color_btns = document.querySelectorAll('#color > p'); color_btns.forEach(function(color) { color.onclick = function () { color_btns.forEach(function(element) { if (element.classList.contains('selected')) { element.classList.remove('selected'); } }); color.classList.add('selected'); document.querySelector('#f_color').value = color.dataset.id; }; });
我在 IE 和 Edge 的控制台中都得到以下输出:
对象不支持属性或方法“ forEach”
搜索该问题后,我了解到IE9和更高版本应支持此功能。我尝试自己定义功能,但没有成功。当我登录该函数时,它被定义为一个函数([native code]内部带有“ ”)。
[native code]
我用.forEacha 替换了每个,for效果很好,
.forEach
for
forEach()
我以为是Array.prototype.forEach这样,而IE的最新版本(以及Edge的所有版本)都拥有它…?
Array.prototype.forEach
返回值[querySelectorAll不是数组,而是NodeList。直到最近才有了forEach(并且与JavaScript的迭代协议兼容,让您将它们用作for-of和表示法的目标)。
querySelectorAll
forEach
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)。
enumerable
configurable
writable
true
当NodeList了forEach,这也成了 迭代 ,这意味着你可以通过一个内容循环NodeList通过for- of回路,并使用NodeList(在数组初始化比如,在传播符号)在其他地方可迭代的预期。
NodeList
for- of
在实践中,具有使用可迭代性的功能(例如for-of循环)的浏览器也可能已经提供的这些功能NodeList,但是要确保(也许您正在转码并包括的polyfillSymbol),我们需要再做一遍。事情:在其Symbol.iterator属性中添加一个函数以创建迭代器:
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 IE11 function 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(); }); // Iterable if (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 class="container"> <div>one</div> <div>two</div> <div>three</div> <div>four</div> </div>
在HTMLCollection由归国getElementsByTagName(以及各种其他旧的API)没有被定义为可迭代的,但如果你喜欢,你也可以做到这一点的HTMLCollection为好。这是一个执行botyNodeList(如果需要)和HTMLCollection(如果需要)的循环:
HTMLCollection
getElementsByTagName
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是一个断开连接的集合,因此不会发生行为。)