当前位置: 首页 > 知识库问答 >
问题:

querySelectorAll上的forEach在最近的Microsoft浏览器中不起作用

澹台成龙
2023-03-14

我正在制作一个关于产品(颜色等)选择的脚本,它可以在除Internet Explorer(11)&Edge之外的所有浏览器中工作。

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的控制台中得到以下输出:

对象不支持属性或方法“for each”

    null

共有1个答案

黄淇
2023-03-14

大多数DOM方法和集合属性实际上不是数组,而是集合:

  • QuerySelectorAll返回一个静态NodeList(在调用时匹配元素的快照)。
  • GetElementsByTagNameGetElementsByTagNamensGetElementsByClassNameParentNode上的Children属性(元素是父节点)返回实时HTMLCollection实例(如果更改DOM,则该更改将实时反映在集合中)。
  • GetElementsByName返回一个活动的NodeList(不是快照)。

NodeList最近才获得Foreach(以及keys和几个其他数组方法)。HTMLCollection没有也不会;事实证明,添加它们会破坏Web上太多的代码。

不过,NodeListHTMLCollection都是可迭代的,这意味着您可以使用for-of循环遍历它们,通过扩展将它们扩展为数组([...theCollection])等。但是,如果您运行的浏览器NodeList没有foreach,那么它可能太老了,不具备任何ES2015+特性,比如for-of或迭代。

由于NodeList被指定为具有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;
}

在这种情况下,直接赋值很好,因为enumerableconfigurablewritable都应该是true,并且它是一个值属性。(enumerabletrue,这让我很惊讶,但在chrome/chromium/Edge/etc、Firefox、旧的遗留Edge和Safari上就是这样定义的)。

在您自己的代码中,如果您愿意,也可以使用HTMLCollection来实现这一点,只是要注意,如果您使用的是一些旧的DOM库,如MooTools或YUI或诸如此类的库,如果您将Foreach添加到HTMLCollection中,它们可能会混淆。

正如我前面所说,NodeListHTMLCollection都被指定为可迭代(因为这个Web IDL规则)。如果您遇到了一个具有ES2015+功能的浏览器,但由于某种原因没有使集合可迭代,您也可以polyfill:

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
    });
}

(HTMLCollection也是如此。)

下面是一个同时使用这两种功能的示例,在IE11上尝试一下(例如)(尽管它只演示foreach),在IE11上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 - won't happen on IE11 because it doesn't have Symbol
    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>
 类似资料:
  • 问题内容: 我正在编写用于选择产品(颜色等)的脚本,该脚本可在除 Internet Explorer (11)和 Edge 之外的所有浏览器中使用。 我将每个参数的选择放入数组中,并使用方法将函数应用于它们。 color参数的示例: 我在 IE 和 Edge 的控制台中都得到以下输出: 对象不支持属性或方法“ forEach” 搜索该问题后,我了解到IE9和更高版本应支持此功能。我尝试自己定义功能

  • 我正试图通过C#最小化Microsoft Edge浏览器。除了微软Edge之外,其他浏览器如Chrome、Firefox、Internet Explorer都运行良好。 有人能帮帮我吗。

  • 问题内容: 我在使用SWT浏览器组件时遇到了一些麻烦。我正在运行带有Sun的Java SE 1.6的Ubuntu 11.04 AMD64和Eclipse 3.7 我的问题是我的浏览器无法初始化。当我使用SWT.NONE标志实现时,出现错误 然后当我尝试使用SWT.MOZILLA标志时,我得到 我怀疑这部分是因为我正在使用XULRunner2,但是我更喜欢使用WebKit,在Eclipse 3.7中

  • 问题内容: 我的HTML文件中有这个: 这在CSS文件中: Firefox在Firebug中返回CSS错误。难道我做错了什么? 按照W3C规范的功能,它应该工作。 问题答案: 查看规范中给出的语法: 似乎需要删除属性名称和要使用的单位之间的逗号: 但是,即使您使用正确的语法,也不会起作用。事实证明,截至 3的级别3版本没有已知的实现 2012年 … 2020年。更糟糕的是,截至最新的规范编辑草案仍

  • 问题内容: 我尝试使用以下代码将必填字段告知必填字段,但在Safari浏览器中不起作用。码: 上面的代码在firefox中工作。 您可以让我知道JavaScript代码或任何workarround吗? 是javascript新功能 谢谢 问题答案: Safari(自2017年3月26日起最新版本10.1)不支持此属性,您需要使用JavaScript。 该页面包含一个hacky解决方案,该解决方案应

  • 问题内容: alert(myVar1); return false; var myVar1; 上面的代码在IE,FF和Opera中引发错误,表明return语句必须包含在函数中。但它可以在Safari和Chrome中运行(显示)。 以上代码已在全局范围内编写。以外的所有功能。 任何原因? 问题答案: 在javaScript中,将变量移到脚本顶部,然后运行。所以当你运行它会做 这是因为javascr