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

Javascript QuerySelector上的forEach在最近的Microsoft浏览器中不起作用,javascript,arrays,internet-explorer,foreach,microsoft-edge,Javascript,Arrays,Internet Explorer,Foreach,Microsoft Edge,我正在为产品(颜色等)的选择制作一个脚本,它适用于除Internet Explorer(11)和Edge之外的所有浏览器 我将每个参数的选择放在一个数组中,并使用array.forEach()方法对它们应用一个函数 颜色参数的示例: var color_btns = document.querySelectorAll('#color > p'); color_btns.forEach(function(color) { color.onclick = function () {

我正在为产品(颜色等)的选择制作一个脚本,它适用于除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;
    };
});
我在IE和Edge的控制台中都得到以下输出:

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

在搜索了这个问题后,我了解到这个函数应该是。我试图自己定义函数,但没有成功。当我记录函数时,它被定义为一个函数(内部有“
[本机代码]
”)

我将每个
.forEach
替换为
for
,它工作得很好

  • 但是我怎样才能让它工作呢
  • Internet Explorer和Edge是否有
    forEach()
    的特定用法

我还以为它是Array.prototype.forEach,最近版本的IE(以及所有版本的Edge)都有它…?

虽然它看起来像一个数组,但实际上它是一个节点列表,与数组没有相同的功能。 改用for循环

color_btns = document.querySelectorAll('#color > p'); 

for (var i = 0; i < color_btns.length; i++) {
    color_btns[i].onclick = function () { 
        for (var j = 0; j < color_btns.length; j++) {
            if(color_btns[j].classList.contains('selected')) { 
                color_btns[j].classList.remove('selected');
            }
        }
    color_btns[i].classList.add('selected'); 
    document.querySelector('#f_color').value = color_btns[i].dataset.id;
    };
}
color\u btns=document.queryselectoral('color>p');
对于(变量i=0;i
的返回值不是数组,而是数组。这是最近才得到的
forEach
(并且与JavaScript的迭代协议兼容,让您可以将它们作为
for of
和spread notation的目标)

您可以轻松地使用polyfill
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
being
true
令我惊讶,但这就是它在Chrome、Firefox、Edge和Safari上的本机定义)


同时
NodeList
got
forEach
它也变得可编辑,这意味着您可以通过
for
循环遍历
NodeList
的内容,并在需要编辑的其他地方使用
NodeList
(例如,数组初始值设定项中的扩展表示法)

在实践中,具有使用可写性功能的浏览器(如
for of
循环)也可能已经提供了
节点列表
的这些功能,但为了确保(可能您正在传输并包含
符号
)的多边形填充,我们需要做第二件事:向其
符号添加一个函数。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
),在IE11上
NodeList
本机不具备这些功能:

//仅使用ES5功能,因此它在IE11上运行
函数日志(){
if(控制台类型!==“未定义”&&console.log){
console.log.apply(控制台,参数);
}
}
if(节点列表的类型!=“未定义”&&NodeList.prototype){
//弗雷奇
if(!NodeList.prototype.forEach){
//是的,这里真的不需要“Object.defineProperty”
控制台日志(“添加的forEach”);
NodeList.prototype.forEach=Array.prototype.forEach;
}
//易熔性
if(typeof Symbol!=“未定义”&&Symbol.iterator&&NodeList.prototype[Symbol.iterator]){
log(“添加了Symbol.iterator”);
Object.defineProperty(NodeList.prototype、Symbol.iterator、{
值:Array.prototype[Symbol.itereator],
可写:对,
可配置:true
});
}
}
日志(“测试forEach”);
document.queryselectoral(“.container div”).forEach(函数(div){
var html=div.innerHTML;
div.innerHTML=html[0].toUpperCase()+html.substring(1.toLowerCase();
});
//宜人的
if(typeof Symbol!=“未定义”&&Symbol.iterator){
//在这里使用eval避免在IE11上引起语法错误
日志(“可测试性”);
评估(
'for(document.queryselectoral的const div(“.container div”){'+
“div.style.color=”蓝色“;”+
'}'
);
}

一
二
三
四

好的,让我们从这里开始,在JavaScript中,我们有一些情况称之为类似于数组的数组,这意味着即使它看起来像数组,也不是真正的数组

例如,函数中的参数或节点列表中的参数

即使是所有的现代浏览器都知道你喜欢把它改成数组并且工作得很好,例如在IE和其他一些浏览器中,在Nodelist上使用数组函数是不受支持的

因此,如果您支持多种浏览器,最好先将它们转换为数组,然后再对其执行任何活动

将类似数组的值转换为实数组的方法很少

ES5中广泛使用的一种结构是:

Array.prototype.slice.call(YourNodeList)

因此,您可以:

var allDivs = document.querySelectorAll("div");
var allRealDivsArray = Array.prototype.slice.call(allDivs);
但是如果你使用ES6,甚至还有更简洁的方法,只要确保你使用babel将它们转换为ES5,例如那些不支持数组循环的旧浏览器肯定也不支持ES6

两种非常常见的方法是:

1)使用数组。从

const allDivs = document.querySelectorAll("div");
const allRealDivsArray = Array.from(allDivs);
2)使用[…数组]

const allDivs = document.querySelectorAll("div");
const allRealDivsArray = [...allDivs];

color\u btns
不是一个数组,而是一个-“: