練習問題の解答解説(ステップごと)
以下は先ほどの練習問題 A/B/C それぞれについて、考え方 → コード → 各要素ごとの処理の流れ → 出力の確認 → よくある間違い を順に説明します。
問題 A(やさしい)
問題: 配列 [2, 4, 6] の各要素を 3で割った値の配列 を作る。
考え方
mapは配列の各要素を順に取り出してコールバック関数に渡す。- 「3で割る」処理をコールバックに書いて、その戻り値を新しい配列の要素にする。
コード
let arr = [2, 4, 6];
let result = arr.map(n => n / 3);
console.log(result); // 期待値: [0.6666666666666666, 1.3333333333333333, 2]
JavaScriptステップごとの処理(要素別)
- 最初の要素
2を取り出す →2 / 3→0.6666666666666666を返す → 新配列の最初の要素になる。 - 次の要素
4を取り出す →4 / 3→1.3333333333333333を返す → 新配列の2番目に入る。 - 最後の要素
6を取り出す →6 / 3→2を返す → 新配列の3番目に入る。
出力(確認)
[0.6666666666666666, 1.3333333333333333, 2](小数の丸めは JS の浮動小数点表現による)
よくある間違い
mapの中でreturnを忘れると要素がundefinedになる(アロー関数で中括弧を使う場合に特に注意)。- NG例:
arr.map(n => { n / 3 })→ すべてundefined。 - 正しくは
arr.map(n => { return n / 3 })またはarr.map(n => n / 3)。
- NG例:
問題 B(中級)
問題: 次の配列から price を 税込(10%) にした配列を作る。
let items = [{name:'Pen', price:100}, {name:'Notebook', price:250}];
JavaScript考え方
- 元の配列はオブジェクトの配列。
mapの各コールバックで新しいオブジェクトを返して新配列を作る。 - 元オブジェクトを直接変更(副作用)しないように、新しいオブジェクトを作る(不変性を保つのが安全)。
税抜 price に 10% を掛けるときは price * 1.1。必要なら小数点の丸めも行う(今回は丸めなしで示す)。
コード(丸めなし)
let items = [{name:'Pen', price:100}, {name:'Notebook', price:250}];
let withTax = items.map(item => ({
name: item.name,
priceWithTax: item.price * 1.1
}));
console.log(withTax);
// 期待値: [{name:'Pen', priceWithTax:110}, {name:'Notebook', priceWithTax:275}]
JavaScriptステップごとの処理(要素別)
- 最初のオブジェクト
{name:'Pen', price:100}を取り出す。item.price * 1.1→100 * 1.1→110。- 新オブジェクト
{name: 'Pen', priceWithTax: 110}を返す → 新配列の1番目。
{name:'Notebook', price:250}→250 * 1.1→275→{name:'Notebook', priceWithTax:275}を返す → 新配列の2番目。
出力(確認)
[{name:'Pen', priceWithTax:110}, {name:'Notebook', priceWithTax:275}]
追加(小数点を 2 桁で丸めたい場合)
let withTaxRounded = items.map(item => ({
name: item.name,
priceWithTax: Math.round(item.price * 1.1 * 100) / 100
}));
JavaScriptMath.round(... * 100) / 100を使うと小数第2位で四捨五入できる(通貨表示に便利)。
よくある間違い
- 元の
itemsのオブジェクトを直接書き換してしまうと副作用になる:- NG例:
items.map(item => { item.price = item.price * 1.1; return item; })
→ 元配列のpriceが変わってしまう(避けたほうが良い)。
- NG例:
- オブジェクトを返すときに丸括弧の書き忘れ(アロー関数で中括弧
{}とオブジェクトリテラルを区別する点):- NG:
items.map(item => { name: item.name, priceWithTax: ... })は関数ボディと解釈される →undefined。 - 正:
items.map(item => ({ name: item.name, priceWithTax: ... }))
- NG:
問題 C(応用)
問題: 数字の配列 [3,7,11] を、2乗して文字列 'x^2 = y' の形にした配列を作る。
例:3 → "3^2 = 9"
考え方
- 各要素
xに対してx * xで 2乗を計算し、テンプレートリテラル(`${}`)で'x^2 = y'の形の文字列を作る。
コード
let nums = [3, 7, 11];
let formatted = nums.map(x => `${x}^2 = ${x * x}`);
console.log(formatted); // 期待値: ["3^2 = 9", "7^2 = 49", "11^2 = 121"]
JavaScriptステップごとの処理(要素別)
3→3 * 3 = 9→ テンプレートで"3^2 = 9"を返す。7→49→"7^2 = 49"を返す。11→121→"11^2 = 121"を返す。
出力(確認)
["3^2 = 9", "7^2 = 49", "11^2 = 121"]
変化例(カッコを付ける、あるいは表記を変える)
nums.map(x =>${x} squared is ${x * x})→["3 squared is 9", ...]
よくある間違い
- 数値を文字列に変換する必要はない(テンプレートリテラルが自動で文字列化する)。
- もし
${x*x}と書くときに括弧忘れをして\${x}^2 = ${x * x}“ のように正しく書くこと(計算順は普通に動くが見づらくなるケースあり)。
最後に:自分で試すためのチェックリスト
- コードをブラウザの開発者ツールや Node.js で実行してみる。
map中でconsole.logを入れて各要素がどう渡されるか確認すると理解が深まる(例:arr.map((v,i,a) => { console.log(v,i,a); return ... }))。mapが返すのは常に新しい配列であることを確認する(console.log(arr === newArr)はfalse)。
