Internet Explorer(11)&Edgeを除くすべてのブラウザーで機能する、製品に関する選択(色など)のスクリプトを作成しています。
各パラメーターの選択肢を配列に入れ、array.forEach()
メソッドを使用してそれらに関数を適用します。
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の両方のコンソールに次の出力が表示されます。
オブジェクトはプロパティまたはメソッド「forEach」をサポートしていません
問題について検索したところ、この関数は IE 9以降 でサポートされているはずです)であることがわかりました。成功しました。関数をログに記録すると、関数として定義されます(「_[native code]
_」を使用)。
私はすべての_.forEach
_をfor
に置き換えました。
forEach()
の特定の使用法はありますか?私はそれが_Array.prototype.forEach
_であり、IE(およびEdgeのすべてのバージョン))の最近のバージョンにそれがあると思いました...?
querySelectorAll
の戻り値は配列ではなく、 NodeList です。つい最近、forEach
(およびJavaScriptのiterationプロトコルとの互換性があり、それらを_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;
}
_
この場合、enumerable
、configurable
、およびwritable
はすべてtrue
である必要があり、値のプロパティであるため、直接割り当ては問題ありません。 (enumerable
がtrue
であることには驚きましたが、それがChrome、Firefox、Edge、およびSafariでネイティブに定義されている方法です)。
NodeList
がforEach
を取得すると、それもiterableになり、_for-of
_ループを介してNodeList
のコンテンツをループし、反復可能な他の場所でNodeList
を使用できます期待されます(たとえば、配列初期化子のスプレッド表記)。
実際には、反復可能性を使用する機能(_for-of
_ループなど)を備えたブラウザーも、NodeList
のこれらの機能をすでに提供している可能性がありますが、(Symbol
のポリフィルを変換して含めることを確実にするため)、 2番目のことを行う必要があります。イテレータを作成する_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
});
}
_
両方を一緒に行う:
_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
にはこれらの機能がネイティブに備わっていない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"; ' +
'}'
);
}
_
_<div class="container">
<div>one</div>
<div>two</div>
<div>three</div>
<div>four</div>
</div>
_
HTMLCollection
(およびその他のさまざまな古いAPI)によって返されるgetElementsByTagName
は反復可能として定義されていませんが、必要に応じて、HTMLCollection
に対してもこれを行うことができます。以下は、NodeList
(必要な場合)とHTMLCollection
(必要な場合)を実行するループです。
_for (const ctor of [typeof NodeList !== "undefined" && NodeList, typeof HTMLCollection !== "undefined" && HTMLCollection]) {
if (ctor && ctor.prototype && !ctor.prototype.forEach) {
// (Yes, there's really no need for `Object.defineProperty` here)
ctor.prototype.forEach = Array.prototype.forEach;
if (typeof Symbol !== "undefined" && Symbol.iterator && !ctor.prototype[Symbol.iterator]) {
Object.defineProperty(ctor.prototype, Symbol.iterator, {
value: Array.prototype[Symbol.itereator],
writable: true,
configurable: true
});
}
}
}
_
HTMLCollection
はliveなので、コレクションの内容に影響を与えるDOMへの変更はすぐにコレクションに反映され、驚くべき結果になる可能性があることに注意してください動作。 (NodeList
は切断されたコレクションであるため、動作は発生しません。)
さて、ここから始めましょう。JavaScriptでは、それを呼び出す場合がありますArray-like、つまり、配列のように見えても、そうではありません実際の配列...
たとえば、arguments関数またはあなたの場合Nodelist...
IEおよびその他の一部のブラウザでは、たとえば、Nodelistの配列関数を使用してサポートされていない...
したがって、幅広いブラウザーをサポートしている場合は、ブラウザーでアクティビティを実行する前に、それらを配列に変換することをお勧めします...
Array-like値を実際のArrayに変換する方法はいくつかあります。 ..
ES5で広く使用されているのはこの構造です。
Array.prototype.slice.call(YourNodeList);
だからあなたはできる:
var allDivs = document.querySelectorAll("div");
var allRealDivsArray = Array.prototype.slice.call(allDivs);
ただし、ES6を使用している場合は、より洗練された方法があります。たとえば、配列のようなループをサポートしていない古いブラウザーはES6を確実にサポートしないため、それらをbabelを使用してES5に変換してください。 ..
それらを行うための非常に一般的な2つの方法は次のとおりです。
1)Array.fromを使用する
const allDivs = document.querySelectorAll("div");
const allRealDivsArray = Array.from(allDivs);
2)[...配列]を使用
const allDivs = document.querySelectorAll("div");
const allRealDivsArray = [...allDivs];
配列のように見えるかもしれませんが、実際には配列と同じ機能を持たないNodeListです。代わりに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;
};
}