15

フォームを検証できるように、オブジェクトの 2 つの配列をマージしようとしています。通常の concat メソッドは、この状況では機能しないようです。Concat は、通常の数値配列と文字列配列では機能しますが、オブジェクト配列では機能しません。回線var allTags = allInputs.concat(allSelects);が機能​​しません。

var allInputs = document.getElementsByTagName("input");
alert("Inputs: " + allInputs.length);

var allSelects = document.getElementsByTagName("select");
alert("Selects: " + allSelects.length);

var allTags = allInputs.concat(allSelects);
alert("allTags: " + allTags.length);
4

5 に答える 5

26

Concat は、通常の数値配列と文字列配列では機能しますが、オブジェクト配列では機能しません。

実際にはそうですが、NodeListインスタンスにはconcatメソッドArray#concatがなく、それらをフラット化したいことを識別する手段がありません (配列ではないため)。

しかし、それでもかなり簡単です(ただし、以下の警告を参照してください)。この行を変更します。

var allTags = allInputs.concat(allSelects);

var allTags = [];
allTags.push.apply(allTags, allInputs);
allTags.push.apply(allTags, allSelects);

実例| ソース

これはちょっとしたトリックを使用して機能します:Array#push配列に追加する可変数の要素を受け入れ、(この場合は) に指定さFunction#applyれた値と任意の配列のようなオブジェクトを引数として使用して関数を呼び出します。 . インスタンスは配列に似ているため、リストのすべての要素を喜んで配列にプッシュします。thisallTagsNodeListpush

のこの動作Function#apply(2 番目の引数が実際に配列である必要はない) は、仕様で非常に明確に定義されており、最新のブラウザーで十分にサポートされています。

悲しいことに、IE6 と 7 は上記をサポートしていません (特にホスト オブジェクトを使用していると思います — NodeLists —Function#applyの 2 番目の引数に) 。:-) IE8 もそうではありません。これはより問題です。IE9 は満足しています。

IE8 以前をサポートする必要がある場合は、悲しいことに、退屈な古いループで立ち往生していると思います。

var allInputs = document.getElementsByTagName('input');
var allSelects = document.getElementsByTagName('select');
var allTags = [];

appendAll(allTags, allInputs);
appendAll(allTags, allSelects);

function appendAll(dest, src) {
  var n;

  for (n = 0; n < src.length; ++n) {
    dest.push(src[n]);
  }

  return dest;
}

実例| ソース

それIE8以前(およびその他)で機能します。

于 2013-02-02T19:02:38.390 に答える
2

document.get[something]NodeListを返します。これは配列に非常によく似ていますが、多くの特徴的な機能があり、そのうちの2つは次のとおりです。

  • concatメソッドは含まれていません
  • アイテムのリストはライブです。これは、ドキュメントがリアルタイムで変更されると変更されることを意味します。

NodeListを実際の配列に変換することに問題がない場合は、次の手順を実行して、目的の効果を実現できます。

var allInputs  = document.getElementsByTagName("input")
  , allSelects = document.getElementsByTagName("select")
;//nodeLists

var inputList  = makeArray(allInputs)
  , selectList = makeArray(allSelects)
;//nodeArrays

var combined   = inputList.concat(selectList);

function makeArray(list){
  return Array.prototype.slice.call(list);
}

DOMへの変更を反映するためにリアルタイムで更新する機能を含め、元のNodeListのすべての動作が失われますが、それは実際には問題ではないと思います。

于 2013-02-02T19:04:11.027 に答える
1

扱っているのはHTMLCollectionsであり、それらはライブコレクションです(つまり、ノードをDOMに追加すると、そのノードは自動的にコレクションに追加されます。

そして悲しいことに、それは方法を持っていませんconcat...理由のために。あなたがする必要があるのは、それを配列に変換し、そのライブ動作を失うことです:

var allInputsArray = [].slice.call(allInputs),
    allSelectsArray = [].slice.call(allSelects),
    allFields = allInputsArray.concat(allSelectsArray);
于 2013-02-02T19:05:00.350 に答える
1

ページまたはフォームに表示される順序で dom オブジェクトを収集する簡単な方法を見つけました。まず、オブジェクトにダミー クラス スタイル 'reqd' を作成し、次を使用して、ページに表示される順序でリストを作成します。収集したいオブジェクトにクラスを追加するだけです。

var allTags = document.querySelectorAll("input.reqd, select.reqd");
于 2013-02-04T22:28:17.327 に答える
0

underscore.js をまったく調べましたか? あなたができる

 var allSelectsAndInputs = _.union(_.values(document.getElementsByTagName("input")),_.values(document.getElementsByTagName("select")));

詳細については、http: //underscorejs.org/#extendを参照してください。

この関数はオブジェクトを対象としていますが、この設定でも機能します。

于 2013-02-02T19:03:05.237 に答える