jjzjj

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

coder 2024-07-21 原文

我正在制作一个用于选择产品(颜色等)的脚本,它适用于除 Internet Explorer (11) 和 Edge 之外的所有浏览器。

我将每个参数的选择放在一个数组中,并使用 array.forEach() 方法对它们应用一个函数。

颜色参数示例:

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

我在 IEEdge 的控制台中得到以下输出:

Object doesn't support property or method 'forEach'

经过查找问题,得知这个函数应该是supported by IE 9 and newer .我试图自己定义函数,但没有成功。当我记录该函数时,它被定义为一个函数(内部带有“[native code]”)。

我用 for 替换了每个 .forEach 并且它工作得很好,

  • 但是我怎样才能让它发挥作用呢?
  • Internet ExplorerEdgeforEach() 有特定用法吗?

我认为它是 Array.prototype.forEach 并且最新版本的 IE(以及所有版本的 Edge)都有它......?

最佳答案

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

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

不过,NodeListHTMLCollection 都是可迭代,这意味着您可以使用 for-of 循环遍历它们>,通过 spread ([...theCollection]) 等将它们扩展成一个数组。但是如果您在 NodeList 没有 forEach,它可能太老了,无法拥有任何 ES2015+ 功能,例如 for-of 或迭代。

由于 NodeList 被指定为具有 forEach,您可以安全地对其进行 polyfill,而且真的很容易做到:

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这是一个有值(value)的属性(property)。 (enumerabletrue 令我感到惊讶,但这就是它在 Chrome/Chromium/Edge/Etc.、Firefox、旧版 Legacy Edge 和 Safari 上的原生定义)。

在你自己的代码中,如果你愿意,你也可以使用 HTMLCollection 来做到这一点,只是要注意,如果你使用一些旧的 DOM 库,比如 MooTools 或 YUI 或类似的,它们可能是如果将 forEach 添加到 HTMLCollection 会感到困惑。


正如我之前所说,NodeListHTMLCollection 都被指定为可迭代的(因为 this Web IDL rule ¹)。如果您遇到具有 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.iterator],
        writable: true,
        configurable: true
    });
}

(对于 HTMLCollection 也是如此。)

这是一个使用两者的实例,在(例如)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 - 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.iterator],
            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 是可迭代的,但它没有标有 iterable declaration ,在 JavaScript DOM 绑定(bind)中奇怪的是 doesn't 意味着某些东西是可迭代的,这意味着它有 forEach, entries, keys, values, and 它是可迭代的。但是没有用 iterable 声明标记的 HTMLCollection 仍然是可迭代的。相反,它是可迭代的,因为 this Web IDL rule如前所述。

关于javascript - querySelectorAll 上的 forEach 在最近的 Microsoft 浏览器中不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46929157/

有关javascript - querySelectorAll 上的 forEach 在最近的 Microsoft 浏览器中不起作用的更多相关文章

  1. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  2. ruby-on-rails - date_field_tag,如何设置默认日期? [ rails 上的 ruby ] - 2

    我想设置一个默认日期,例如实际日期,我该如何设置?还有如何在组合框中设置默认值顺便问一下,date_field_tag和date_field之间有什么区别? 最佳答案 试试这个:将默认日期作为第二个参数传递。youcorrectlysetthedefaultvalueofcomboboxasshowninyourquestion. 关于ruby-on-rails-date_field_tag,如何设置默认日期?[rails上的ruby],我们在StackOverflow上找到一个类似的问

  3. ruby-on-rails - s3_direct_upload 在生产服务器中不工作 - 2

    在Rails4.0.2中,我使用s3_direct_upload和aws-sdkgems直接为s3存储桶上传文件。在开发环境中它工作正常,但在生产环境中它会抛出如下错误,ActionView::Template::Error(noimplicitconversionofnilintoString)在View中,create_cv_url,:id=>"s3_uploader",:key=>"cv_uploads/{unique_id}/${filename}",:key_starts_with=>"cv_uploads/",:callback_param=>"cv[direct_uplo

  4. ruby-on-rails - openshift 上的 rails 控制台 - 2

    我将我的Rails应用程序部署到OpenShift,它运行良好,但我无法在生产服务器上运行“Rails控制台”。它给了我这个错误。我该如何解决这个问题?我尝试更新ruby​​gems,但它也给出了权限被拒绝的错误,我也无法做到。railsc错误:Warning:You'reusingRubygems1.8.24withSpring.UpgradetoatleastRubygems2.1.0andrun`gempristine--all`forbetterstartupperformance./opt/rh/ruby193/root/usr/share/rubygems/rubygems

  5. ruby-on-rails - 相关表上的范围为 "WHERE ... LIKE" - 2

    我正在尝试从Postgresql表(table1)中获取数据,该表由另一个相关表(property)的字段(table2)过滤。在纯SQL中,我会这样编写查询:SELECT*FROMtable1JOINtable2USING(table2_id)WHEREtable2.propertyLIKE'query%'这工作正常:scope:my_scope,->(query){includes(:table2).where("table2.property":query)}但我真正需要的是使用LIKE运算符进行过滤,而不是严格相等。然而,这是行不通的:scope:my_scope,->(que

  6. ruby-on-rails - Ruby - 如何从 ruby​​ 上的 .pfx 文件中提取公钥、rsa 私钥和 CA key - 2

    我有一个.pfx格式的证书,我需要使用ruby​​提取公共(public)、私有(private)和CA证书。使用shell我可以这样做:#ExtractPublicKey(askforpassword)opensslpkcs12-infile.pfx-outfile_public.pem-clcerts-nokeys#ExtractCertificateAuthorityKey(askforpassword)opensslpkcs12-infile.pfx-outfile_ca.pem-cacerts-nokeys#ExtractPrivateKey(askforpassword)o

  7. ruby-on-rails - "assigns"在 Ruby on Rails 中有什么作用? - 2

    我目前正在尝试学习RubyonRails和测试框架RSpec。assigns在此RSpec测试中做什么?describe"GETindex"doit"assignsallmymodelas@mymodel"domymodel=Factory(:mymodel)get:indexassigns(:mymodels).shouldeq([mymodel])endend 最佳答案 assigns只是检查您在Controller中设置的实例变量的值。这里检查@mymodels。 关于ruby-o

  8. ruby-on-rails - 使用 javascript 更改数据方法不会更改 ajax 调用用户的什么方法? - 2

    我遇到了一个非常奇怪的问题,我很难解决。在我看来,我有一个与data-remote="true"和data-method="delete"的链接。当我单击该链接时,我可以看到对我的Rails服务器的DELETE请求。返回的JS代码会更改此链接的属性,其中包括href和data-method。再次单击此链接后,我的服务器收到了对新href的请求,但使用的是旧的data-method,即使我已将其从DELETE到POST(它仍然发送一个DELETE请求)。但是,如果我刷新页面,HTML与"new"HTML相同(随返回的JS发生变化),但它实际上发送了正确的请求类型。这就是这个问题令我困惑的

  9. 带有 attr_accessor 的类上的 Ruby instance_eval - 2

    我了解instance_eval和class_eval之间的基本区别。我在玩弄时发现的是一些涉及attr_accessor的奇怪东西。这是一个例子:A=Class.newA.class_eval{attr_accessor:x}a=A.newa.x="x"a.x=>"x"#...expectedA.instance_eval{attr_accessor:y}A.y="y"=>NoMethodError:undefinedmethod`y='forA:Classa.y="y"=>"y"#WHATTT?这是怎么回事:instance_eval没有访问我们的A类(对象)然后它实际上将它添加到

  10. ruby-on-rails - rails 上的 ruby : radio buttons for collection select - 2

    我有一个集合选择:此方法的单选按钮是什么?谢谢 最佳答案 Rails3中没有这样的助手。在Rails4中,它是collection_radio_buttons. 关于ruby-on-rails-rails上的ruby:radiobuttonsforcollectionselect,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/18525986/

随机推荐