つくる 作品リストを一覧にする
このレッスンで分かること
- 配列とループを組み合わせて一覧の文字列を組み立てられます
i + 1を使えばインデックスから 1 始まりの番号を作れます- 空配列のときに何を返すかを、自分で決めて書けます
つくる 作品リストを一覧にする とは
第5章で学んだ配列とループを全部使って、作品名の配列から番号付きの一覧文字列を作る関数を書きます。
ここまでで何ができるようになったか
第5章では、複数の値をまとめて扱う方法を身に付けました。振り返っておきましょう。
| レッスン | できるようになったこと |
|---|---|
| 配列のきほん | [] で配列を作り、arr[0] と arr.length で中身を扱う |
| 要素を足す・取り除く | push pop shift unshift で中身を変える |
| for ループで合計を求める | インデックスを使って先頭から順に処理する |
| for-of で配列を走査する | 番号を書かずに要素そのものを受け取る |
| while で条件を満たす間くり返す | 回数が決まらないくり返しを条件で止める |
| break と continue | 要素を飛ばす、途中で抜ける |
第4章までは、値をひとつずつ変数に入れて if で分岐するところまででした。そこに配列とループが加わったことで、件数が変わっても書き直さなくていいコードが書けるようになっています。これは「一覧」を扱うすべての画面の土台です。
今回はその総仕上げとして、山田 太郎さんの作品名の配列から、そのまま画面に出せる番号付きの一覧を組み立てます。
buildWorkList(["プロフィールサイト", "自己紹介カード"]);
// "1. プロフィールサイト
// 2. 自己紹介カード"組み立ての設計を先に決める
いきなりコードを書く前に、やることを 3 つに分けます。
- 空配列だったら、専用のメッセージを返して終わる
- 配列を先頭から順にまわし、
番号 + ". " + 作品名の行を作る - 行と行のあいだに改行を入れてつなぎ、できた文字列を返す
この 3 つに分けてしまえば、あとは 1 つずつ書くだけです。難しく見える課題も、日本語で手順に分解してから書くと迷子になりません。
手が止まる原因のほとんどは、コードの書きかたが分からないことではなく、何をすればよいかが決まっていないことです。書く前に日本語で手順を並べる習慣は、この先ずっと効きます。
番号を作る
作品名の配列にはインデックスしか無いので、表示用の番号は自分で作ります。インデックスは 0 から始まり、番号は 1 から始まるので、差はいつも 1 です。
インデックス i | 表示したい番号 | 式 |
|---|---|---|
0 | 1 | i + 1 |
1 | 2 | i + 1 |
2 | 3 | i + 1 |
番号が必要なので、ここは for-of ではなく通常の for を選びます。前のレッスンの使い分けがそのまま効いてきます。
const titles = ["プロフィールサイト", "自己紹介カード"];
for (let i = 0; i < titles.length; i++) {
console.log((i + 1) + ". " + titles[i]);
}
// 1. プロフィールサイト
// 2. 自己紹介カード(i + 1) をカッコで囲んでいる点に注目してください。カッコが無いと i + 1 + ". " の順に左から評価され、たまたま今回は同じ結果になりますが、意図を示すためにも囲んでおくのが安全です。
改行でつなぐ
行と行をつなぐ改行は \n と書きます。バックスラッシュと n の 2 文字で 1 つの改行を表します。
ここで気を付けたいのが、改行を入れる場所です。素直に「各行のうしろに \n を足す」と書くと、最後の行のうしろにも改行が付いてしまいます。
let result = "";
for (let i = 0; i < titles.length; i++) {
result += (i + 1) + ". " + titles[i] + "\n"; // 末尾に余分な改行が残る
}見た目では気付きにくいのに、文字列を比べるテストでは容赦なく失敗します。回避のしかたは、2 行目以降を書く前に改行を足すことです。
let result = "";
for (let i = 0; i < titles.length; i++) {
if (i > 0) {
result += "\n"; // 2 行目以降だけ、前に改行を足す
}
result += (i + 1) + ". " + titles[i];
}i > 0 という条件がそのまま「2 行目以降」を意味します。1 行目のときだけ改行を足さない、という考えかたです。
区切り文字を要素の「うしろ」ではなく「あいだ」に置く、という考えかたは一覧を組み立てるときの定番です。カンマ区切りでも同じことが起きるので、ここで型として覚えてしまいましょう。
空配列のときを決める
最後に、作品がまだ 1 つも無い場合です。何も考えずに書くと、空文字列 "" が返ります。画面には何も出ず、まるで壊れているように見えます。
そこで、空配列のときは専用のメッセージを返すことにします。判定は関数の先頭でやってしまうのがきれいです。
function buildWorkList(titles) {
if (titles.length === 0) {
return "作品はまだありません";
}
// ここから先は、要素が 1 つ以上あることが保証されている
}先に特殊なケースを片付けておくと、そのあとのコードは「要素がある場合」だけを考えればよくなります。条件分岐が入り組まず、読みやすさが段違いです。
空のとき、ゼロのとき、ひとつだけのとき。この 3 つはプログラムが壊れやすい境界で、テストでも必ず確認されます。今回の課題でもテストに入っているので、忘れずに対応してください。
全体の骨組みを決める
3 つの部品がそろったので、置く順番を決めます。空判定、ためる変数の用意、ループ、最後に返す、の順です。
function buildWorkList(titles) {
// 1. 空配列なら専用メッセージを返して終わる
// 2. ためる変数を "" で用意する
// 3. for でまわし、2 行目以降には先に改行を足してから 1 行ぶんを足す
// 4. できあがった文字列を返す
}この 4 行のコメントを先に書いてから、上から順に中身を埋めていくと迷いません。書き終えたらコメントは消しても残しても構いません。
要素が 1 つのときを手で追っておきましょう。i は 0 のときだけ回り、i > 0 は偽なので改行は入らず、"1. プロフィールサイト" になります。改行の付きかたが心配なときは、この確認がいちばん早いです。
動作を確かめる
書けたら、頭の中ではなく実際に呼び出して確かめましょう。
console.log(buildWorkList([]));
console.log(buildWorkList(["プロフィールサイト"]));
console.log(buildWorkList(["プロフィールサイト", "自己紹介カード", "スキル一覧の表"]));3 件のときの出力は、番号が 1 から 3 まで並び、行のあいだにだけ改行が入った形になります。ここまで来れば、あとは作品が何件になっても関数を書き直す必要はありません。第8章で学ぶ DOM と組み合わせれば、この文字列を実際の画面に表示できます。
よくある間違い
- 末尾に余分な改行が残る — 各行のうしろに
\nを足すと最後にも付きます。あいだに入れる書きかたにしましょう
// result += titles[i] + "\n"; // 末尾に余分
if (i > 0) { result += "\n"; } // あいだにだけ入る
result += titles[i];- 番号がずれる —
iをそのまま使うと0から始まる一覧になります。表示用はi + 1です
// result += i + ". " + titles[i]; // 0. から始まる
result += (i + 1) + ". " + titles[i]; // 1. から始まる- ためる変数をループの中で宣言する —
let result = ""をループの本体に書くと毎周からっぽに戻り、最後の 1 行しか残りません。宣言はループの前です
要件
- 関数名は
buildWorkList、引数は文字列の配列titles1 つ、戻り値は文字列 - 各行は
番号 + ". " + 作品名の形にすること。番号は1から始まる - 行と行のあいだだけを
\nでつなぐこと (末尾に余分な改行を付けない) - 空配列のときは
"作品はまだありません"を返すこと
入出力例
buildWorkList([]) → "作品はまだありません"
buildWorkList(["プロフィールサイト"]) → "1. プロフィールサイト"
buildWorkList(["プロフィールサイト","自己紹介カード"]) → "1. プロフィールサイト
2. 自己紹介カード"
buildWorkList(["プロフィールサイト","自己紹介カード","スキル一覧の表"]) → "1. プロフィールサイト
2. 自己紹介カード
3. スキル一覧の表"
buildWorkList(["プロフィールサイト","自己紹介カード","スキル一覧の表","ブログ","ポートフォリオ"]) → "1. プロフィールサイト
2. 自己紹介カード
3. スキル一覧の表
4. ブログ
5. ポートフォリオ"