document.getElementsByTagName の 2 回の呼び出しによって返される 2 つの NodeLists を結合する方法はありますか?
たとえば、次のコードがあります
var inputs = documentElement.getElementsByTagName('input');
var selects = document.getElementsByTagName('select');
結果をループしたい。1ループで可能ですか?
前もって感謝します!
document.getElementsByTagName の 2 回の呼び出しによって返される 2 つの NodeLists を結合する方法はありますか?
たとえば、次のコードがあります
var inputs = documentElement.getElementsByTagName('input');
var selects = document.getElementsByTagName('select');
結果をループしたい。1ループで可能ですか?
前もって感謝します!
args配列のようなオブジェクトを配列にするのと同じArray.prototype.slice.callを使用できるようです。(ここを参照)
var inputs = document.getElementsByTagName('input');
var selects = document.getElementsByTagName('select');
inputs = Array.prototype.slice.call(inputs);
selects = Array.prototype.slice.call(selects);
var res = inputs.concat(selects);
alert(res.length);
それらを結合することはできませんが、次のように 1 つのループで順番にループすることはできます。
for ( var i = 0; i < inputs.length + selects.length; i++ ) {
var element = ( i < inputs.length ) ? inputs[i] : selects[i-inputs.length];
}
または、jQuery を使用して、一度にすべてを選択することもできます。
$('input, select')
document.querySelectorAll("input, select");
私の知る限り、NodeList
型は不変です (たとえば、この記事を参照してください)。つまり、独自のオブジェクトを生成する必要があります。
簡単な方法は、配列を作成し、すべての要素をその配列にコピーすることです。
var inputs = documentElement.getElementsByTagName('input');
var selects = document.getElementsByTagName('select');
var all = new Array(inputs.length + selects.length);
var index = 0;
for (i = 0; i < inputs.length; i++)
all[index++] = inputs[i];
for (i = 0; i < selects.length; i++)
all[index++] = selects[i];
all
変数には、2 つのノード セットの和集合が含まれます。
function mergeNodeLists(a, b) {
var slice = Array.prototype.slice;
return slice.call(a).concat(slice.call(b));
}
console.log( mergeNodeLists( inputs, selects ) ); // => [input, select]
ブックマークレットの私のショートコード:
var e, t = d.getElementsByTagName('textarea'), u = d.getElementsByTagName('input'), i = t.length;
while(e = (i > 0) ? t[--i] : u[-i--]){ if(e.offsetHeight > 0)... }
これをまとめました。ループごとにifと.lengthを実行するとオーバーヘッドが少し発生する可能性がありますが、要素の数が極端に増えない限り、それはわずかだと思います。
inputs = div.getElementsByTagName('input');
selects = div.getElementsByTagName('select');
for (i=0; i<inputs.length+selects.length; i++) {
element = (i<inputs.length ? inputs[i] : selects[i-inputs.length]);
// do whatever with element
}
まず、次のように Array.prototype を使用して配列を連結できると考えました。
Array.prototype.concat.call(selects, inputs);
しかし、うまくいかないので、ノード コレクションから配列を作成して連結しました。そのように見えます:
(function () {
var inputs = document.getElementsByTagName('input'),
selects = document.getElementsByTagName('select'),
result,
i,
node;
function convert (collection) {
var a = [];
for (var i = 0, length = collection.length; i < length; i++) {
a.push(collection[i]);
}
return a;
}
// concatenation && convertation
result = Array.prototype.concat(convert(inputs), convert(selects));
// traversing
i = result.length;
while(node = result[--i]) {
alert(node.getAttribute('name'));
}
})();
今日、私は間違いなく以下を使用します:
Chrome、Firefox 3.5 以降、IE8 以降
var elements = document.querySelectorAll('a');
for (var i = 0, element; (element = elements[i]); i++) {
console.log(element);
}
IE11 以降、Firefox 24 以降、Chrome 30 以降 (実験が有効になっている場合)
let elements = document.querySelectorAll('a');
for (let i = 0, element; (element = elements[i]); i++) {
console.log(element);
}
次の理由から、「element = elements[i]」は「elements.length」よりも優先されます。
「ノード リストは、多くの場合、フィルタを使用してノード イテレータとして実装されます。これは、長さのようなプロパティを取得するのが O(n) であり、長さを再チェックしてリストを反復すると O(n^2) になることを意味します。」
私が覚えている限りでは、O(1) の配列アクセスとは異なります。
詳細: