タイトルの通りなんですが、HTMLの<form>
をJavaScriptで取得する際、
JavaScript:
1 2document.getElemetById('フォームのID');
↑これで取得する方法がポピュラーかと思うのですが、
JavaScript:
1 2document.forms./*フォームのidまたはname属性*/;
↑これでも取得できるそうです。
また、それを受けて試してみたところ
JavaScript:
1 2document./*フォームのname属性*/; 3document./*フォームのname属性*/./*子要素のidやname属性*/;
↑これでも要素の取得ができるようなんです。
(子要素というのは<input>
などです。formに関連しない要素は試してません。)
短く書けるならそのほうが良いとは思うのですが、
一番下の方法は、なんとなく不安な感じもしてます。
これらそれぞれの手法を取る場合の長所・短所など教えていただけないでしょうか?
技術的な長所・短所だけでなく、使用上の所感・ご意見なども参考になるので是非教えて下さい。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答3件
0
<form name> はform要素群の中で一意である
name属性を持つのは、form要素だけではありません。
同じname属性値を持つ要素が複数存在した場合、document.formName
は HTMLCollection を返します。
HTML
1<form name="foo"></form> 2<img name="foo" src="foo.jpg"> 3<script> 4console.log(document.foo); // HTMLCollection(2) [form, img, foo: form] 5</script>
form要素のname属性値が他のname属性値と重複しない場合、document.formName
は要素ノードを返します。
HTML
1<form name="foo"></form> 2<script> 3console.log(document.foo); // <form name="foo"></form>``` 4</script>
将来的にHTML文書が変更されて、返り値が上記2つの状態に変化することを想定するなら、条件分岐処理でどちらのパターンにも対応できるように書かなければなりません。
JavaScript
1const foo = document.foo; // 要素ノードかHTMLCollectionか不明なノード 2const fooList = foo.length ? foo : [foo]; // HTMLCollection でなければ、配列に格納しておく 3 4for (let i = 0, len = fooList.length; i < len; ++i) { 5 const foo = fooList[i]; 6 7 if (foo.tagName === 'FORM') { 8 console.log(foo); // <form name="foo"></form> 9 break; 10 } 11}
既存の名前空間を破壊する
document.body
のように予め用意されたプロパティであっても、容赦なく破壊します。
HTML
1<form name="body"></form> 2<script> 3console.log(document.body); // <form name="body"></form> 4 5/** 6 * body要素ノードにform要素ノード挿入を試みる 7 */ 8document.body.appendChild(document.createElement('form')); 9console.log(document.body); // <form name="body"><form></form></form> 10</script>
本事象を回避する為に、組み込みのプロパティ名がドット記法で参照可能な名前に限定されている事に着目し、ドット記法では表せない名前にする方法があります。
例えば、-
はその一つであり、Selectors APIとも相性が良いので、お勧めです。
document.forms
form.formname
は下記コードの簡易版です。
JavaScript
1document.forms['formName']
form要素ノードに限定されている為、<img name>
等の他要素のname属性値と衝突する事はありません。
document.forms
は HTMLCollection を返すAPIで現在でも実用できます。
ただし、HTMLCollection は id
または name
属性値を検索するので、id属性値とは衝突します。
DOM Standard仕様上は「コレクションの中で初めに出現する要素」を参照します。
Return the first element in the collection for which at least one of the following is true:
- it has an ID which is key;
- it is in the HTML namespace and has a name attribute whose value is key;
が、「Google Chrome 78.0.3904.87」は順序に関わらず、id属性値を優先しました。
name属性値と衝突しないように気をつけた方が良さそうです。
HTML
1<form name="foo"></form> 2<form id="foo"></form> 3<script> 4console.log(document.forms['foo']); // <form id="foo"></form> 5</script>
古いAPIが使えないわけではない
querySelector
がある今現在でも getElementById
は現役です。
「古い」は「使わない理由」になりませんが、具体的な問題点があるなら、それは理由になります。
各々の性質を見極めて、状況判断で新旧に囚われずに選択する方がコードの幅が広がって良いと思います。
Re: H40831 さん
投稿2019/11/01 13:00
編集2019/11/02 09:11総合スコア18189
0
ベストアンサー
はじめに
コメントを受けて改訂した内容となります(回答の文中で斜体となる編集箇所です)。
※ご意見でもいいとのことでしたので
短所しかないですよ
ドットで区切るプロパティPATH(造語:某Nodeモジュール内で関数の引数名に記述されていた propertyPath
より)の記法は、DOMの概念がなかった頃の名残です。
最初はDOMなんて無かったですから。
プロパティPATHの時代
まだNetscapeNavigatorが息づいていた頃。JavaScriptは完全に趣味で「JavaScriptポケットリファレンスの改定2版(1999年5月)」で独習していました。その頃の記法です。
当時はJavaScriptは危険だと言われていて、ウェブサイトもTABLE要素で無理やりデザインし、GIFアニメで表現する程度だったんです(あの Dreamweaver でさえもTABLEデザイン用に特化されていました)。
DOMの時代
それから時を経てDOMの整備が進み、TABLEデザインとHTML+CSSの混在、HTML+CSS2、XHTML+CSS2と変わり、今のHTML5+CSS3に至ってます。
CSS2になってもしばらくは、JavaScriptの危険性(ブラウザ実装による)を謳う人も多かったんですよ。
閑話休題
プロパティPATHの記法に話を戻すと、短所しかないです。というか、使いどころが減りました。
HTML上でFORM要素__以下に含まれる入力フィールドの要素__ のname属性が変わるとJavaScriptでも大量の書き換えが発生します。ブラケットで書く場合には変数を使えますがコードが長いことに変わりなかった。
今もコードを書くのは「人」ですよね。
なので「書き換え事案の発生のたびに typo を誘発する。」ことに。
幸いにもJavaScriptが主流になるのはDOMが整備されてからでした。
DOMが整備された頃、 ビルトインオブジェクトを拡張して多機能化(今では禁忌の手法)する Ajaxライブラリ(Prototype.js) や DOM操作に主眼をおいたAjaxライブラリ(jQuery)が登場したのです。
こういう歴史を知っていると、普通にDOMを使っている今は「あるべき姿に改善されていった」だけでしかない。ポピュラーというのも違うんですよね。モダンという言葉が似合っていると思います。
querySelectorAll("input[type=text]")
で複数のテキストフィールドを取得できる素晴らしさを、昔の自分に教えるとどうなるだろうと感じます。
コメントへの回答:(追記)
「書き換え事案の発生のたびに typo を誘発するとは?」
要はヒューマンエラーの削減に関することです。
- プロパティPATHは必ず フォームフィールド部分で javascript の編集がつきまとっていました
- DOMはそうでもなくなった(AjaxでPOSTする事例をコードで示してみます)。
javascript
1// コメントを受け、関数化したものに変更しています 2function getFormInputs( elem ) { 3 var postJson = {} 4 , form, fields, field, name, value 5 ; 6 7 if( "string" === typeof elem ) { 8 // DOM のセレクタを与えた場合 9 form = document.querySelector( elem ); 10 } 11 else if( elem instanceof HTMLFormElement ){ 12 // getElementsById() で得られたHTMLFormElement や 13 // window.forms[`${formName}`] を与えた場合 14 form = elem; 15 } 16 // 例外処理は省略 17 18 fields = form.querySelectorAll("input") 19 for(var i=0; i<fields.length; ++i ){ 20 field = fields[i]; 21 name = field.getAttribute("name") || field.id; 22 value = field.value || ''; 23 24 postJson[name] = value; 25 } 26 return postJson; 27} 28console.log( JSON.stringify( getFormInputs( {HTMLFormElement|selector} ) ) ); // AjaxでPOSTするデータ
このように、HTMLの変化があっても使える 使い回しの効く コードになります。
人為的なコード改変が減る=ヒューマンエラーも減ると言えますよね。
ヒューマンエラーは、人が集中を欠くと発生しちゃいます。些細な悩み事でもです。
ヒューマンエラーの発生率を下げるにはコード自体の改変量を減らすなどの工夫が不可欠ですが、DOMならそれができます。
最後に
最初に回答した時点では、言葉足らずのために多くが曖昧な表現となっていました。
そのような稚拙な文章をお読みになられた方々にはこの場を借りて謝罪いたします。
貴重なお時間を割いてしまい、申し訳ありません。
また、再度の推敲を促してくださった、質問者 (H40831 さん)、他のコメントを投げてくださった、think49さん、yamabejpさんには、併せて感謝申し上げます。
編集事由につきましては、コメント欄でのやりとりをご覧くださいませ。
AkitoshiManabe
投稿2019/10/31 13:41
編集2019/11/01 22:35総合スコア5434
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/10/31 21:23
2019/11/01 01:42
2019/11/01 01:45
2019/11/01 05:47
2019/11/01 06:28
2019/11/01 06:46
2019/11/01 09:08
2019/11/01 12:08
2019/11/01 21:29
2019/11/03 04:14
2019/11/03 04:29
2019/11/03 04:56 編集
0
レガシーな書き方だと
javascript
1<script> 2window.addEventListener('DOMContentLoaded', ()=>{ 3 console.log(document.forms["f1"].elements["n13"].id); 4 console.log(document.forms[1].elements[1].id); 5 console.log(document.f3.n31.id); 6}); 7</script> 8<form name="f1"> 9<input name="n11" id="i11"> 10<input name="n12" id="i12"> 11<input name="n13" id="i13"> 12</form> 13<form name="f2"> 14<input name="n21" id="i21"> 15<input name="n22" id="i22"> 16<input name="n23" id="i23"> 17</form> 18<form name="f3"> 19<input name="n31" id="i31"> 20<input name="n32" id="i32"> 21<input name="n33" id="i33"> 22</form>
昔はなんでもnameでした。
nameが原則uniqueである必要がないことから色々工夫され
getElementsByName的な処理もされましたが、
現在はquerySelectorでタグ名、id、クラスなどで
きちんと系統だったアクセスするのが主流です。
投稿2019/11/01 01:54
総合スコア116688
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/11/02 15:57