つくる プロフィールを変数にする
このレッスンで分かること
- 第2章で学んだ 6 つの道具を 1 つの関数の中で組み合わせられます
- 外から届いた値は、受け取った直後に型をそろえておくと後が楽になります
- 複数行の文面はテンプレートリテラルで組み立てます
つくる プロフィールを変数にする とは
第2章の総まとめです。宣言から型変換、真偽値の判定、文面の組み立てまでを 1 本の関数で通して書きます。
ここまでで何ができるようになったか
第2章では、値を扱うための道具を 6 つ手に入れました。整理すると次の通りです。
| 学んだこと | 道具 | プロフィールでの使いどころ |
|---|---|---|
| 変数の宣言 | const / let | 名前と肩書きを保持する |
| 型の確認 | typeof | 届いた値が想定どおりか調べる |
| 数値への変換 | Number() | 入力欄の "3" を計算に使う |
| 文字列への変換 | String() | 数値を文面に混ぜる |
| 真偽値への変換 | Boolean() | 自己紹介が入力済みか調べる |
| 文面の組み立て | テンプレートリテラル | 複数行のカードを作る |
第1章では文字列と数値をそのまま書いていました。第2章を終えた今は、外から届いた値を受け取り、型をそろえ、文面に組み立てるところまでできます。これはプロフィールサイトの表示処理そのものです。
まだできないのは、値によって表示を切り替えることです。「自己紹介が未入力なら別の文言を出す」といった分岐は第4章で扱います。この回では、分岐の材料となる真偽値までを用意します。
位置付け このレッスンで作る関数は、第9章のフォーム入力チェックで実際に使う形の原型です。今は文字列を返すだけですが、その戻り値を画面に出すのが第8章と第9章の役割になります。
作るもの
入力欄から届いた 3 つの値を受け取り、確認用のプロフィールカードを 4 行の文字列で返す関数を作ります。
buildProfileText("山田 太郎", "3", "はじめまして");
// 山田 太郎
// Web エンジニアを目指しています
// 経験 4 年目
// 自己紹介の入力 true1 行目が名前、2 行目が肩書き、3 行目が経験年数、4 行目が自己紹介の入力状況です。肩書きは全員共通の固定文言なので、引数では受け取らず関数の中で持ちます。
経験年数は、届いた値に 1 を足した「何年目か」を表示します。入力欄から届く値は文字列なので、そのまま足すと連結になってしまいます。前のレッスンで学んだとおり Number() で変換してから計算します。
4 行目の true と false は、自己紹介が入力されているかどうかを表します。第9章で入力チェックの表示を切り替えるときの材料になる値です。
組み立ての順番
処理は 3 段階に分けて書きます。この順番はこの関数に限らず、値を扱う処理の基本形です。
- 固定値を
constで宣言する - 届いた値を変換して型をそろえる
- 文面を組み立てて返す
まず 1 段階目です。肩書きは書き換えないので const で宣言します。
const title = "Web エンジニアを目指しています";次に 2 段階目です。経験年数を数値に、自己紹介の有無を真偽値に変換します。どちらも変換したら書き換えないので const を使います。
const years = Number(yearsText);
const hasBio = Boolean(bio);Number("") が 0 になること、Boolean(null) が false になることは、前の 2 回で確認したとおりです。未入力でも NaN にならず、エラーも起きません。
最後に 3 段階目です。テンプレートリテラルで 4 行を組み立てます。
let text = `${name}
${title}`;
text = text + `
経験 ${years + 1} 年目`;ここでは組み立ての途中経過を持つので let を使います。一度に書ける場合は const 1 つで済ませても構いません。どちらでも結果は同じです。
書き方の選択 4 行すべてを 1 つのテンプレートリテラルで書く方法と、行ごとに足していく方法があります。行数が固定なら前者、後の章で行が増減するようになったら後者が書きやすくなります。
変換をどこでやるか
この関数で一番大事な設計判断は、変換の位置です。years + 1 を計算する場所で毎回 Number(yearsText) + 1 と書くこともできますが、そうすると変換が処理のあちこちに散らばります。
// 変換が散らばっている例
const line3 = `経験 ${Number(yearsText) + 1} 年目`;
const line4 = `自己紹介の入力 ${Boolean(bio)}`;関数の入口で変換して名前を付けておけば、以降の行では型を気にせずに済みます。
// 入口で変換する例
const years = Number(yearsText);
const hasBio = Boolean(bio);
const line3 = `経験 ${years + 1} 年目`;
const line4 = `自己紹介の入力 ${hasBio}`;行数はほとんど変わりませんが、years という名前が付いたことで「ここから先は数値である」と読み手に伝わります。第6章で関数を分けるようになると、この違いがさらに効いてきます。
処理の途中で値が想定どおりか確かめたくなったら、typeof を使ってください。
console.log(typeof years); // "number" 変換できている
console.log(typeof hasBio); // "boolean"現場の話 型がそろっていない値を関数の奥まで持ち込むと、原因の場所を特定しにくくなります。入口でそろえる、というだけで調査時間が大きく変わります。
完成した関数の読み方
書き上がった関数は、上から読むだけで処理の意図が分かる形になっているはずです。最初のかたまりで固定値を決め、次のかたまりで型をそろえ、最後のかたまりで文面を作る。この 3 つのかたまりが見えていれば、後から読む人も修正箇所をすぐ見つけられます。
たとえば肩書きを変えたいなら 1 つ目のかたまり、経験年数の数え方を変えたいなら 3 つ目のかたまりだけを見ればよい、という具合です。逆に、変換と組み立てが 1 行に混ざっていると、どこを直せばよいのか読み解く手間がかかります。
次の章に向けて
第3章では演算子を学びます。この関数で使った + に加えて、値を比べる ===、条件を組み合わせる && と ||、既定値を用意する ?? が加わります。第2章で作った真偽値は、第3章と第4章で「処理を分ける」ための入力になります。
つまり、この章でやったのは判断の材料集めです。材料がそろったので、次はその材料を使って判断する方法を学ぶ、という流れになります。第4章まで進むと、この関数の 4 行目を 自己紹介の入力 true ではなく 自己紹介を入力してください のような文言に置き換えられるようになります。
よくある間違い
1 つ目は、経験年数を変換せずに足してしまうケースです。
const yearsText = "3";
console.log(`経験 ${yearsText + 1} 年目`); // "経験 31 年目"Number(yearsText) + 1 に直すと 4 になります。文字列と数値の + は連結になる、という第2章の中心的な落とし穴です。
2 つ目は、真偽値を文字列と混同するケースです。
const hasBio = Boolean("");
console.log(`自己紹介の入力 ${hasBio}`); // "自己紹介の入力 false"
console.log(`自己紹介の入力 ${"false"}`); // 同じ表示だが値は文字列埋め込んだ結果の見た目は同じでも、false と "false" は別の値です。前者は falsy、後者は truthy なので、第4章で分岐に使うと結果が変わります。
3 つ目は、行の末尾に余分な改行や空白を残すケースです。
return `${name}
${title}
`; // 末尾に改行が 1 つ残るテンプレートリテラルは書いたとおりの空白と改行をそのまま含みます。テストが通らないときは、まず末尾の改行とインデントを疑ってください。関数の中で字下げして書くと、2 行目以降の先頭に空白が入る点にも注意が必要です。
要件
- 関数名は buildProfileText、引数は name (文字列) と yearsText (文字列または数値) と bio (文字列または null) の 3 つ
- 肩書きは const で宣言し、yearsText は Number、bio は Boolean で変換する
- 文面はテンプレートリテラルで組み立て、行の区切りは改行 1 つ。末尾に改行は付けない
- 戻り値は 4 行を改行でつないだ 1 つの文字列
入出力例
buildProfileText("山田 太郎", "3", "はじめまして") → "山田 太郎
Web エンジニアを目指しています
経験 4 年目
自己紹介の入力 true"
buildProfileText("佐藤 花子", 0, "デザイン担当です") → "佐藤 花子
Web エンジニアを目指しています
経験 1 年目
自己紹介の入力 true"
buildProfileText("山田 太郎", "", "") → "山田 太郎
Web エンジニアを目指しています
経験 1 年目
自己紹介の入力 false"
buildProfileText("山田 太郎", "5", null) → "山田 太郎
Web エンジニアを目指しています
経験 6 年目
自己紹介の入力 false"
buildProfileText("", "10", "自己紹介") → "
Web エンジニアを目指しています
経験 11 年目
自己紹介の入力 true"