Aym*_*Dev 7 javascript arrays foreach internet-explorer microsoft-edge
我正在制作一个关于产品(颜色等)的选择的脚本,它适用于除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;
};
});
Run Code Online (Sandbox Code Playgroud)
我在IE和Edge的控制台中得到以下输出:
对象不支持属性或方法'forEach'
在搜索了这个问题后,我了解到IE 9及更新版本应支持此功能.我试图自己定义功能但没有成功.当我记录该函数时,它被定义为一个函数([native code]内部带有" ").
我用一个替换.forEach了for它,它工作得很好,
forEach()针对Internet Explorer和Edge的特定用法?我以为它是Array.prototype.forEach最新版本的IE(和所有版本的Edge)都有它......?
T.J*_*der 18
返回值querySelectorAll不是数组,而是NodeList.这只是最近才得到的forEach(兼容JavaScript的迭代协议,让你用它们作为目标for-of和传播符号).
您可以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;
}
Run Code Online (Sandbox Code Playgroud)
直接分配在这种情况下细,因为enumerable,configurable和writable都应该true和它的价值属性.(enumerable正true让我感到惊讶,但这是它是如何定义本身在Chrome,火狐,边缘和Safari).
当NodeList了forEach,这也成了迭代,这意味着你可以通过一个内容循环NodeList通过for-of回路,并使用NodeList(在数组初始化比如,在传播符号)在其他地方可迭代的预期.
在实践中,具有使用可迭代性(如for-of循环)的功能的浏览器也可能已经提供了这些功能NodeList,但为了确保(可能是您正在进行转换并包含polyfill Symbol),我们需要做一秒钟thing:向其Symbol.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
});
}
Run Code Online (Sandbox Code Playgroud)
两者兼顾:
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
});
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个使用两者的实例,尝试使用(例如)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
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"; ' +
'}'
);
}Run Code Online (Sandbox Code Playgroud)
<div class="container">
<div>one</div>
<div>two</div>
<div>three</div>
<div>four</div>
</div>Run Code Online (Sandbox Code Playgroud)
好的,让我们从这里开始,在JavaScript中,有些情况我们称之为Array-like,这意味着即使它看起来像一个数组,它也不是真正的数组...
例如函数中的参数或您所用的节点列表 ...
甚至所有现代的浏览器都知道您想要将其更改为Array并正常运行,例如在IE和其他一些浏览器中,使用Nodelist上的数组函数也不支持...
因此,如果您支持广泛的浏览器,最好在对其进行任何活动之前将它们转换为数组...
有几种方法可以将类似数组的值转换为实际的数组 ...
ES5中广泛使用的一种结构是:
Array.prototype.slice.call(YourNodeList);
因此,您可以执行以下操作:
var allDivs = document.querySelectorAll("div");
var allRealDivsArray = Array.prototype.slice.call(allDivs);
Run Code Online (Sandbox Code Playgroud)
但是,如果您使用ES6,甚至可以使用更巧妙的方法,例如,请确保使用babel将它们转换为ES5,因为那些不支持像数组一样循环的旧浏览器肯定也不会支持ES6。 ..
两种非常常见的方法是:
1)使用Array.from
const allDivs = document.querySelectorAll("div");
const allRealDivsArray = Array.from(allDivs);
Run Code Online (Sandbox Code Playgroud)
2)使用[... Array]
const allDivs = document.querySelectorAll("div");
const allRealDivsArray = [...allDivs];
Run Code Online (Sandbox Code Playgroud)