配列と文字列とは何か
配列は「値を順番に並べるための入れ物」、文字列は「文字を順番に並べたテキスト」です。どちらも“順序がある並び”ですが、決定的な違いがあります。ここが重要です:配列は変更可能(要素の追加・削除・並び替えができる)、文字列は不変(作った文字列を直接書き換えられない)。この性質が、使えるメソッドや扱い方に大きく影響します。
インデックスと長さ(アクセスの基本)
0始まりで要素や文字にアクセスする
const arr = ["A", "B", "C"];
const str = "ABC";
console.log(arr[0]); // "A"
console.log(str[0]); // "A"
JavaScript配列も文字列も先頭はインデックス 0 です。ここが重要です:配列の末尾は arr[arr.length - 1]、文字列の末尾は str[str.length - 1] または str.at(-1) で安全に取れます。
範囲外アクセスは undefined
console.log(arr[99]); // undefined
console.log(str[99]); // undefined
JavaScript存在しない位置を参照してもエラーにはならず undefined。ここが重要です:範囲チェック(0 ≤ i < length)を徹底すると安全です。
変更可能性とメソッド(できることの違い)
配列は“その場で”変えられる、文字列は新しく作り直す
const arr = [1, 2, 3];
arr.push(4); // [1,2,3,4](配列は可変)
arr.splice(1, 1); // [1,3](削除も可)
let str = "ABC";
// str[0] = "X"; // 何も起きない(文字列は不変)
str = "X" + str.slice(1); // "XBC"(新しい文字列を作って置き換える)
JavaScriptここが重要です:配列は push/pop/splice/sort など“破壊的メソッド”が豊富。文字列は replace/slice/substr などで“新しい文字列”を返すのが基本です。
メソッドのラインナップの違い
// 配列:並びや要素操作
[3,1,2].sort((a,b)=>a-b); // 並び替え
[1,2,3].map(x => x*2); // 変換(非破壊)
[1,2,3,4].filter(x => x%2===0); // 抽出(非破壊)
// 文字列:検索・抽出・置換・分割
"Hello".includes("el"); // true
"Hello".slice(1, 4); // "ell"
"2025-12-14".split("-"); // ["2025","12","14"]
"foo bar".replace("bar","baz"); // "foo baz"
JavaScriptここが重要です:配列は“要素集合をいじる”、文字列は“テキストを加工する”。目的に合ったメソッドを選ぶのが早道です。
反復と変換(ループの書き方と発想の違い)
ループは似ているが“何を返すか”が違う
for (const ch of "ABC") console.log(ch); // 文字を順に
for (const v of [10, 20, 30]) console.log(v); // 要素を順に
const doubled = [1,2,3].map(x => x*2); // [2,4,6]
const upper = "abc".toUpperCase(); // "ABC"(文字列は map がないので別API)
JavaScriptここが重要です:配列は map/filter/reduce を使うと“新しい配列”で返せます。文字列は同等の「文字列版 map」はないため、配列へ変換してから処理するなどの工夫をします。
文字列⇄配列の往復(split / join)
const s = "a,b,c";
const arr = s.split(","); // ["a","b","c"] に分割
const back = arr.join("-"); // "a-b-c" に結合
JavaScriptここが重要です:テキストを要素として扱いたいときは split、加工後に文字列へ戻すときは join。往復を意識すると処理が整理されます。
Unicode と“1文字”の難しさ(配列と文字列の本質的違い)
サロゲートペアや結合文字に注意(見た目の1文字が複数コードポイント)
const heart = "💖"; // 見た目1文字でも length は 2 のことがある
console.log(heart.length); // 2 の場合あり
// 安全に“見た目の文字”として扱うならスプレッドで配列化
const chars = [..."A💖B"]; // ["A","💖","B"]
console.log(chars.length); // 3(視覚的な文字数)
JavaScriptここが重要です:文字列の length は“コードユニット数”。絵文字や合成文字は length と見た目の文字数が一致しないことがあります。視覚的な単位で処理したいときは Array.from(str) やスプレッドで“文字配列”にして扱う手が安全です。
実践例で違いを体感する
CSV を配列へ、処理してまた文字列へ戻す
const csv = "pen,120\nnote,300";
const rows = csv.split("\n").map(line => line.split(","));
// rows: [["pen","120"],["note","300"]]
const withTax = rows.map(([name, price]) => [name, Math.round(price*1.1)]);
const out = withTax.map(r => r.join(",")).join("\n");
// out: "pen,132\nnote,330"
JavaScriptここが重要です:テキストは split で“配列の形”に落とすと処理が楽。最後に join で文字列へ戻せば、表示や保存に使えます。
タグ文字列を安全に追加(配列で管理してから結合)
const tags = ["js", "web"];
const next = [...tags, "ux"]; // 非破壊で追加
const asString = next.join(","); // "js,web,ux"
JavaScriptここが重要です:集合の管理は配列が向いています。重複チェックなら includes と filter を組み合わせると簡単です。
よくある落とし穴と回避策
文字列は不変なのに str[0] = "X" のように書き換えようとして“反応しない”ことがあります。必ず slice や replace などで“新しい文字列”を作って代入し直してください。配列の sort や splice は元を破壊するため、状態を共有していると予期せぬ副作用が起きます。コピーしてから操作する([...arr].sort(...)、filter で削除)と安全です。絵文字・合成文字で文字列長と見た目が一致しない問題は、スプレッドや Array.from で“文字配列化”してから処理すると安定します。文字列に map はないため、必要なら split("") やスプレッドで配列化してから map → join("") の流れにしましょう。
まとめ
配列は“変更可能な並び”、文字列は“変更不可のテキスト”。配列は push/pop/splice/sort で形を直接変えられ、map/filter/reduce で非破壊の変換も得意。文字列は slice/replace/split/join で“新しい文字列”として扱うのが基本です。文字数の扱いは Unicode 事情で難しくなることがあり、見た目の文字単位で処理したいときは配列化(スプレッドや Array.from)を活用する。違いを踏まえて“配列で集合を操作し、文字列でテキストを表現する”という役割分担を徹底すれば、初心者でも直感的で壊れにくいコードが書けます。
