保守性の高いコードを書きたいです。JavaScriptでdocument.write("<div id='main'></div>")みたいに書いて、後でこの要素にいろいろなコードでdocument.getElementById('main').innerHTMLします。しかし、その後id名mainを他の名前に変えると、多くのソースコードを手作業で変更しなくてはなりません。この手間を削減するJavaScriptの書き方はありますか?
例えば、
<table id="board">
<tr>
<td id="b0_0">A</td>
<td id="b0_1">A</td>
<td id="b0_2">A</td>
<td id="b0_3">A</td>
・
・
・
上記のようなHTMLを作成する、以下のようなコードがあります。
<table id='board'></table>
<script>
var content = "";
for(i = 0; i < 5; i++){
content += "<tr>"
for(j = 0; j < 4; j++){
content += "<td id='b"+ i + "_" + j +"'>A</td>"
}
content += "</tr>"
}
$('table#board').html(content) // JQueryを使っているつもりです
</script>
このコードの問題点は少なくとも2つあって、
1つは、2重ループ内の「content += "<td id='b"+ i + "_" + j +"'>A</td>"」が読みづらいことです。
2つ目は、今は td id='b0_1'のような形式ですが、このid名を変更しようと思ったときに、変更が容易ではないことです。
特に2つ目は、いろいろな場所にあるコードから$('table#board td#b1_1').html('B')のような操作をしていると、かなり変更が大変です。
こういったことを乗り越えるためのJavaScriptのコード設計法(?)やIDEやライブラリなどがありましたら教えて下さい。よろしくお願いします
No.3ベストアンサー
- 回答日時:
保守性を高めたい、ということですよね。
であるならば、オブジェクト化を進めることだと思います。・マジックナンバー、マジックストリングを排除する
コード内に直接書かれている意味がわからないリテラルのことです。idのmainなどもそうですね。こうしたものはすべてオブジェクト内に定数プロパティとしてまとめておき、それを参照する形で記述します。例えば、こんなオブジェクトを定義しておき、
function Literal() {
var main = "main";
this.main = function(){ return main; }
}
var literal = new Literal();
innerHTMLではこのようにします。
document.getElementById(literal.main()).innerHTML = ……
コード内で"main"を参照する部分はすべてliteral.main()を使います。こうすれば、後で名前を変更したいときは、Literalのvar mainの値を書き換えるだけです。
・処理のメソッド化
処理専用のオブジェクトを用意し、そこに具体的な処理をすべてメソッドとしてまとめます。例えばテーブルを変数contentにまとめている処理なども、こんな感じにします。
function ContentBuilder() {
this.getTable = function(prefix, arraydata){
var content = "";
for(i = 0; i < arraydata.length; i++){
var row_array = arraydata[i];
content += "<tr>";
for(j = 0; j < row_array.length; j++){
content += "<td id='" + prefix + i + "_" + j +"'>" + row_array[j] + "</td>";
}
content += "</tr>";
}
return content;
}
}
var builder = new ContentBuilder();
これで、builderのgetTableを呼び出すことでテーブルのコードが得られるようになります。こんな感じですね。
var data = [
['a','b','c'],
['あ','い','う'],
[1, 2, 3]
];
document.write(builder.getTable("xxx",data));
生成されるタグのidがどのように設定されているか確認してみてください。引数のプレフィクスを変えればIDもすべて変わります。
このように、「変数・定数をすべて1つのオブジェクトにまとめる」「処理はオブジェクトのメソッドにまとめる」というようにしていき、全ての値や処理は必ずこれらのオブジェクトのメソッドを呼び出すようにします。
こうすれば、後で修正する場合も、オブジェクトのプロパティなどを変更すれば、すべてのところで反映されます。更に、定義したオブジェクト類は別ファイルに切り離し、そのスクリプトファイルをロードするようにすれば、ページデザインと処理(ビジネスロジック)も切り離し別々に管理できます。
JavaScriptはオブジェクト指向言語ですから、それを活用しない手はありません。オブジェクト指向についていろいろ調べてみるとよいでしょう。
ご回答ありがとうございます!
JavaScriptでのオブジェクト指向の活用法がわかった気がします!私はJavaをやっていて、より洗練されたオブジェクト指向をもつScalaにも魅力を感じてるので、オブジェクト指向の発想は分かります。JavaScriptは、はっきりとしたクラスはないし(と思っていて)、オブジェクト指向で組もうとすることはありませんでした。
Javaで磨いたオブジェクト指向をこれからはJavaScriptでも発揮したいと思います。ありがとうございました。
No.4
- 回答日時:
そういったケースでは、IDを1つ1つ付けるべきではありません。
行数、列数が分かっていれば('#board td')で一連のリストとして取得するか、
どうしても二次元リストが良ければ('#board tr')で取得してその後('td')で取得すればできます。
ご回答ありがとうございます
私の例が悪すぎました。別に例はtableでなくても良かったです。単に幾つか入れ子になる自然なHTMLを書こうとしただけなんです。
No.2
- 回答日時:
こんな感じでどうでしょう。
2つ目の「変更が容易ではない」の意味がイマイチよく分かりませんが、1つ目の「読みづらいこと」は改善しているし、もしかしたらこれで2つ目も解決したことになるのではと思います。// コードの先頭辺りに定数として書く。「var content = "";」の前かな
var TD_BASE = "<td id='【ID】'>A</td>";
…
for (var j = 0; j < 4; j++) {
var id = "b" + i + "_" + j;
content += TD_BASE.replace("【ID】", id);
}
また、「var TD_BASE = "<td id='【ID】'>A</td>";」ではなく
「var TD_BASE = "<td id='b【row】_【col】'>A</td>";」などとし、replaceを2つ続けるようにしてもいいと思います。
それからfor文内のインデックス変数の部分ですが、「var j = 0」と明示的に書いた方がいいですよ。そうでないとグローバル変数を使うことになります。このケースでは問題は起きませんが、例えばループ内で関数を呼んでいて、その関数の中でもfor文を使っている場合には、同一の変数を使うことになってしまい正しく動かなくなりますので。
この回答への補足
お礼に書き忘れました。
for文の件ありがとうございます。varつけていいことを知りませんでした。for(i=...だと for(window.i= ...になっちゃうんですかね?
ご回答有難うございます。
私の言葉が足りなかったです。
結局やりたいことは、Javaの開発環境Eclipseにある変数名変更する機能がある開発環境とかがあるといいんですけどね。Eclipseだと変数にカーソルを当てて特定のショートカットキーを押すとその変数を使用しているすべての箇所の変数名が編集できるんです。そういった感じ、簡易にid名を変更できたらいいなと思っていました。
しかし、JavaScriptは文字列のなかにコードがあるので、Javaのようにある識別子がどこで使われているか解析するのは困難そうなので、無理なのは覚悟しているのですが。
Webサービスを大規模開発している人たちはどのようにid名などをを管理しているのか気になります。
No.1
- 回答日時:
少々面倒ですが、JavaScript に備わっている DOM を利用するのがもっとも素直でしょう
// 行を作る
var row = document.createElement('tr');
document.getElementById('board').appendChild(row);
// 欄を作る
var cel = document.createElement('td');
cel.id = 'b' + i + '_' + j;
cel.textContent = 'A';
row.appendChild(cel);
jQuery を使っているならば、DOM の記述を多少は簡略化できます
// 行を作る
var row = $('<tr/>').appendTo('table#board');
// 欄を作る
$("<td/>").attr('id', 'b' + i + "_" + j).text('A').appendTo(row);
ご回答ありがとうございます。
DOMを使うのもひとつの手ですね。ただ、結局innerHTMLを使う時と変わらないですね。'b' + i + '_' + jは結局ありますし、
"b{i}_{j}"みたいな記法出来なんですかね?
もしくは、Cのフォーマット指定のようにformat("b%v_%v", i, j)のような関数が文字列を返すとか?ないですかね?
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・人生のプチ美学を教えてください!!
- ・10秒目をつむったら…
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・【大喜利】【投稿~9/18】 おとぎ話『桃太郎』の知られざるエピソード
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
netscapeでもinnerTextやinnner...
-
JavaScriptで特定のtdタグにcla...
-
至急!GetElementById でtdの...
-
javascriptで質問です。 displa...
-
順番にセルの背景色をつけたい
-
リンク色の変更
-
JavaScriptでテーブルをクリッ...
-
マウスをブラウザの外に出した...
-
javascriptで表のます目と画像...
-
【UWSC】HTML内のある部分を抽...
-
IE がクラッシュします
-
一覧から選択した行の行番号を...
-
特定<table>内の<td>の色を変える
-
カレンダーの年月日の横に翌月...
-
jQueryのプラグイン「Tablesort...
-
return trueとreturn falseの用...
-
onchangeイベントを強制的に発...
-
<JavaScript>tableタグを入力不...
-
追加ボタンを押した際に ok ボ...
-
プルダウン 項目が多いので先頭...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
ハイパーリンクを別ウインドウ...
-
特定<table>内の<td>の色を変える
-
JavaScriptで特定のtdタグにcla...
-
プルダウンで選択すると、DBの...
-
【UWSC】HTML内のある部分を抽...
-
tableの任意行にfocusをあてる
-
至急!GetElementById でtdの...
-
一覧から選択した行の行番号を...
-
マウスをブラウザの外に出した...
-
Selenium.ChromeDriverの使い方...
-
「オブジェクトは、このプロパ...
-
リンク色の変更
-
スクロールバーの表示位置を変...
-
テーブルで複数行をまとめて非...
-
Excelで作ったhtmlファイルのサ...
-
チェックボックスにチェックが...
-
JavaScriptでテーブルの行入れ替え
-
テーブル内に表示されている数...
-
【JQuery】テーブルで行選択さ...
-
階層式メニューをtableタグ内に
おすすめ情報