IE 在从控制台调用时支持 forEach(...) 但在从代码调用时不支持

IE supports forEach(...) when invoked fromthe console but not when called from the code

我是 运行 这个代码片段的控制台。在 IE 中,它按预期生成输出。 运行 Cr 和 FF 中的相同供参考证实了行为的一致性。

["a", "b"].forEach(function(element) {
  console.log(element);
});

但是,当 运行 以下脚本时,我收到错误消息,告诉我该对象尚未 forEach(...) 声明。该问题出现在 IE 中,但在 Cr 和 FF 中均未出现。

var menus = document.querySelectorAll("ul.application>li>a");
menus.forEach(function(element) { ... }

我检查了变量 menus 是否已声明,并且选择它的元素会产生我所期望的结果,即 menus[0] 存在并且是一个标签。与其他浏览器相比,它在 IE 中看起来有点不同,但可能只是格式不同。

我有幸使用 Cr 和 FF,所以我在处理 IE 方面的经验有限。谷歌搜索也没有给我太多智慧。

如何进一步解决问题?

基本上 document.querySelectorAll 会 return 一个 nodeList 像对象一样的数组而不是数组。在调用数组函数之前,您必须将其转换为数组。

var menus = document.querySelectorAll("ul.application>li>a");
menus = [].slice.call(menus);
menus.forEach(function(element) { ... });

如果你的环境支持ES6那么你可以使用Array.from()

var menus = document.querySelectorAll("ul.application>li>a");
menus = Array.from(menus);
menus.forEach(function(element) { ... });

不是浏览器的问题,更像是你得到一个类数组对象,用querySelectorAll. It returns a NodeList,是可迭代的,但不是直接用数组方法

不过你可以借用Array.prototype的方法,比如这个

Array.prototype.forEach.call(menu, function(element) { /* ... */ });

如果你想先得到一个真正的数组,你可以用

转换它
array = Array.apply(null, menu);

有点晚了,但如果有人遇到同样的问题并且没有 want/can 没有用 [].forEach.call(elements, fn(el)) 替换所有 forEach 方法,它可能会有用。这是适用于 ie11

的 polyfill
if (! Object.getOwnPropertyDescriptor(NodeList.prototype, 'forEach')) {
    Object.defineProperty(NodeList.prototype, 'forEach', Object.getOwnPropertyDescriptor(Array.prototype, 'forEach'));
}

最好的解决方案是在开头添加一行:

window.NodeList && !NodeList.prototype.forEach && (NodeList.prototype.forEach = Array.prototype.forEach) // make IE support forEach

之后,您可以像在其他普通浏览器中一样在 IE 中使用 forEach。