map とは何か
map は「配列の各要素に同じ処理を適用して、“変換後の新しい配列”を作る」ためのメソッドです。元の配列は変更されない非破壊操作で、要素数は常に同じままです。ここが重要です:map は“変換(mapping)”専用。副作用ではなく「入力→出力」の対応を明確にすることで、読みやすくバグが少ないコードになります。
基本構文と戻り値
使い方の基本
const nums = [1, 2, 3];
const doubled = nums.map(n => n * 2);
console.log(doubled); // [2, 4, 6]
console.log(nums); // [1, 2, 3](元は不変)
JavaScriptmap はコールバック関数の返り値を、そのまま新配列の対応する位置に入れます。元配列は変わらないため、状態管理や参照共有でも安心して使えます。
文字列やオブジェクトの変換
const users = [{ id: 1, name: "A" }, { id: 2, name: "B" }];
const names = users.map(u => u.name); // ["A", "B"]
const withFlag = users.map(u => ({ ...u, active: true }));
// [{id:1,name:"A",active:true}, {id:2,name:"B",active:true}]
JavaScriptここが重要です:オブジェクト要素はスプレッドで“新オブジェクト”を返すと安全。直接書き換えると共有参照に副作用が伝播します。
コールバックに渡される引数(value, index, array)
3引数を使い分ける
const arr = [5, 12, 8];
const result = arr.map((value, index, array) => {
// value: 現在の要素
// index: 現在のインデックス
// array: 元の配列(必要なら参照)
return `${index}:${value}`;
});
console.log(result); // ["0:5", "1:12", "2:8"]
JavaScriptここが重要です:位置情報や配列全体を参照できるため、「インデックスを使ったラベル付け」「隣接要素との比較」などの変換も自然に書けます。
thisArg で文脈を渡す(必要なときだけ)
const cfg = { factor: 10 };
const nums = [1, 2];
const scaled = nums.map(function (x) { return x * this.factor; }, cfg);
console.log(scaled); // [10, 20]
JavaScriptここが重要です:通常は外部変数を直接参照(クロージャ)で十分ですが、this を使う設計なら thisArg が使えます。
よく使う変換レシピ(実務での定番)
型の正規化(文字列→数値、トリム、小文字化)
const raw = [" 10 ", "20", " 30"];
const nums = raw.map(s => Number(s.trim())); // [10, 20, 30]
const tags = ["JS", "Web"];
const norm = tags.map(t => t.toLowerCase()); // ["js", "web"]
JavaScriptここが重要です:比較や検索の前に形式を揃えると、判定が安定します。
安全なデフォルト埋め(null/undefined だけを置換)
const xs = [undefined, 1, null, 2];
const filled = xs.map(x => x ?? 0); // [0, 1, 0, 2]
JavaScriptここが重要です:null 合体演算子(??)なら 0 や “” を誤って上書きしないため、安全に欠損だけを埋められます。
データ整形(必要プロパティだけ抽出・リネーム)
const users = [
{ id: 1, name: "A", email: "a@x" },
{ id: 2, name: "B", email: "b@x" }
];
const dto = users.map(u => ({ userId: u.id, label: `${u.name} <${u.email}>` }));
JavaScriptここが重要です:API 入出力や表示用の“形の変換”は map の王道。変換ロジックを1箇所に集約できます。
重要ポイントの深掘り(挙動・落とし穴・対策)
非破壊であること(副作用を避ける)
map は元配列を変更しません。返す値で“新しい配列を作る”ことが前提です。副作用(外部状態の書き換え)を入れると、短絡評価や合成時に一貫性が崩れます。変換関数は“純粋(入力→出力だけ)”に保ちましょう。
疎配列(空スロット)はスキップされる
const sparse = Array(2); // [ <2 empty items> ]
const mapped = sparse.map(() => 0);
console.log(mapped); // [ <2 empty items> ](穴は埋まらない)
JavaScriptここが重要です:空スロットは map のコールバックが呼ばれず、“穴のまま”伝播します。必要なら Array.from で正規化してから処理します。
const normalized = Array.from(sparse, x => x ?? 0); // [0, 0]
JavaScript非同期処理は map だけで完結しない
const ids = [1, 2];
const promises = ids.map(id => fetch(`/api/${id}`)); // Promise の配列
const results = await Promise.all(promises);
JavaScriptここが重要です:map は“Promise を並べる”まで。実行・集約は Promise.all(または allSettled)で行います。map 内で await は使えません(使うなら for…of で逐次処理)。
パフォーマンスの考え方
map は O(n) の線形走査。重い処理(正規表現、DOM 参照、外部 I/O)を毎要素で行うと遅くなるため、前処理の正規化やキャッシュ(事前に Set 化、ルールのコンパイル)でコストを下げます。複数段の map を重ねるより、1回でまとめて変換すると負荷を減らせることがあります。
map と他メソッドの使い分け(役割を明確に)
map と forEach の違い
forEach は“副作用を実行するだけ”(戻り値なし)、map は“変換結果の配列を返す”。変換したいなら map、ログや外部書き込みなど副作用が目的なら forEach を選びます。
map と filter の組み合わせ
「絞ってから変換」か「変換してから絞る」かで結果が変わることがあります。通常は filter → map の順が分かりやすく安全です。
const products = [
{ name: "A", stock: 0, price: 100 },
{ name: "B", stock: 5, price: 200 },
{ name: "C", stock: 3, price: 150 }
];
const labels = products
.filter(p => p.stock > 0)
.map(p => `${p.name} (${p.price})`);
// ["B (200)", "C (150)"]
JavaScriptmap と reduce の違い
map は「1対1の変換」、reduce は「配列を1つの値へ集約」。合計、最大、連結などは reduce。変換+集約が必要なら、map の結果を reduce へ渡すか、reduce 1本で書きます。
実践例(よくある UI・API の変換仕事)
表示用の加工(フォーマット、ラベル付け)
const temps = [18, 22.5, 25];
const labels = temps.map(t => `${t.toFixed(1)} ℃`); // ["18.0 ℃","22.5 ℃","25.0 ℃"]
JavaScriptID 配列から辞書(連想配列)のキー配列へ
const ids = [10, 20];
const dict = { 10: "A", 20: "B" };
const names = ids.map(id => dict[id] ?? "(unknown)"); // ["A","B"]
JavaScript入力のバリデーションとクレンジング
const raw = [" alice ", "", "BOB "];
const clean = raw
.map(s => s.trim())
.filter(s => s.length > 0)
.map(s => s.toLowerCase());
// ["alice","bob"]
JavaScriptまとめ
map は「各要素を同じルールで変換して、新しい配列を返す」非破壊メソッドです。返り値で“出力の形”を作るのが前提で、副作用は避けるのが基本。疎配列はスキップされるため、必要なら Array.from で正規化を、欠損は ?? で安全に埋める。非同期は Promise の配列にしてから Promise.all で集約。filter・reduce・forEach と役割を明確に使い分ければ、初心者でも直感的で壊れにくい「変換ロジック」を短く正確に書けます。

