【问题标题】:IE supports forEach(...) when invoked fromthe console but not when called from the codeIE 在从控制台调用时支持 forEach(...) 但从代码调用时不支持
【发布时间】:2017-04-29 19:16:01
【问题描述】:

我正在运行这个 sn-p 控制台。在 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 方面的经验是有限的。谷歌搜索也没有给我太多智慧。

如何进一步排除故障?

【问题讨论】:

  • 仅仅是因为 NodeList 不是一个数组(并且 IE/Safari 不支持 NodeList.forEach,请参阅MDN)。
  • 据我所知,querySelectorAll 返回一个HtmlCollection,它与Array 不同,Chrome 可能有一个内部 polyfill,因此它可以在那里工作。
  • “祝福”也是一个诅咒 :) 当浏览器通过实现自己的内部解决方法来弥补时,它们会让 IE 看​​起来很糟糕,也会让你依赖可能会或可能不会改变的自定义实现未来版本 :) 例如,不能保证 Chrome 将继续支持使用 forEach 扩展 HtmlCollection,他们过去已经这样做了 :) 虽然 IE 在很多方面都很糟糕,但如果你必须支持多个浏览器,包括特定版本的 IE,也许出于这些原因,首先在 IE 中运行会更好?
  • @FrançoisWahl 这实际上是一个很好的建议。我只是更喜欢 Cr 和 FF,因为我觉得这些工具更好。但我将不得不更仔细地检查 IE 中的内容。 (好吧,我的专用测试员将不得不这样做,呵呵。)

标签: javascript html foreach internet-explorer-11


【解决方案1】:

基本上document.querySelectorAll 会返回一个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) { ... });

【讨论】:

  • Array.from(menus)Array.apply(null,menus) 有什么关系?我理解文档中描述的概念,但我在这里看到两个知名用户提出的两个不同建议,我想知道为什么会有不同的建议。其中一个即将过时吗?比较常用?
  • @KonradViltersten 两者都很好用。 Array.from 是 ES6 中引入的一个专用函数,用于避免将可迭代对象转换为数组的困难。可迭代对象的一些示例是stringarguments 等。另一方面,Array.apply( 只是一种转换它的方法,如果您的环境不支持 ES6。在 ES5 中有很多方法可以转换它。为了将所有方法集中到一个连接点,他们引入了Array.from
【解决方案2】:

这不是浏览器的问题,更像是你得到了一个类似数组的对象,querySelectorAll。它返回一个NodeList,它是可迭代的,但不能直接使用数组方法。

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

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

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

array = Array.apply(null, menu);

【讨论】:

  • 太对了!这正是它在 IE 控制台中所说的。我认为这只是一种愚蠢的方式来告诉我同样的事情。我的无知是问题所在。现在,为什么它在 FF 和 Cr 中有效?他们对翻译有内在的魔力吗?
  • 他们扩展了语言。
  • Array.from(menus)Array.apply(null,menus) 有什么关系?我理解文档中描述的概念,但我在这里看到两个知名用户提出的两个不同建议,我想知道为什么会有不同的建议。其中一个即将过时吗?比较常用?
  • 根据compatibillity listArray.from 是 ES6 的新功能,不适用于 IE。这意味着,Array.from 不适合您。
【解决方案3】:

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

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

【讨论】:

    【解决方案4】:

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-12-06
      • 2011-06-02
      • 2020-07-24
      • 1970-01-01
      • 1970-01-01
      • 2010-10-19
      • 2019-03-11
      • 1970-01-01
      相关资源
      最近更新 更多