JavaScript基礎 #6 文字列とテンプレートリテラル
#5 オブジェクトと配列 で、データをまとめる2つのデータ構造を見ました。今回の記事は — 文字列 という1つのテーマを深く掘り下げます。よく使うメソッド、テンプレートリテラル、そして正規表現の基本まで。
文字列を作る — 引用符の3種類 #
JavaScriptで文字列を作る引用符は3つあります。
const a = 'シングルクォート';
const b = "ダブルクォート";
const c = `バッククォート(テンプレートリテラル)`;'(シングル)と "(ダブル)は意味的に違いはありません。チームのコンベンションに従って1種類に統一する のが普通です。このシリーズではシングルクォートを使います。
3つ目のバッククォートは テンプレートリテラル と呼ばれる強力な文字列の形ですが、後ほど詳しく見ます。
よく使うメソッド #
長さとインデックスアクセス #
const s = 'ジャバスクリプト';
s.length; // 8
s[0]; // 'ジ'
s.at(0); // 'ジ'
s.at(-1); // 'ト' (負のインデックス — at のみ可能)
at() はES2022で追加されたメソッドです。負のインデックスで末尾から アクセスできます。s[s.length - 1] より短くて明確です。
検索 #
const s = 'hello world';
s.includes('world'); // true
s.indexOf('world'); // 6
s.indexOf('foo'); // -1 (なければ -1)
s.startsWith('hello'); // true
s.endsWith('world'); // true
検索はほぼ常に includes / startsWith / endsWith が直感的です。indexOf は位置まで知りたい場合だけ。
切り出し / 抽出 #
const s = 'hello world';
s.slice(0, 5); // 'hello'
s.slice(6); // 'world'
s.slice(-5); // 'world' (末尾から5文字)
s.substring(0, 5); // 'hello' (slice とほぼ同じ)
昔は substring/substr/slice が微妙に異なっていましたが、新しいコードでは slice 1つに統一する のが良いです。負のインデックスも受け付けて、最も直感的です。
変換 / 整形 #
const s = ' Hello World ';
s.trim(); // 'Hello World'
s.trimStart(); // 'Hello World '
s.trimEnd(); // ' Hello World'
s.toLowerCase(); // ' hello world '
s.toUpperCase(); // ' HELLO WORLD '
s.replaceAll(' ', '_'); // '__Hello_World__'
replaceAll はES2021で追加されました。昔は replace(/g/) で正規表現を使う必要がありましたが、今では単純な置換ならこちらのほうがすっきりします。
分割 / 結合 #
const s = 'りんご,バナナ,ぶどう';
s.split(','); // ['りんご', 'バナナ', 'ぶどう']
['りんご', 'バナナ'].join(','); // 'りんご,バナナ'
// 1文字ずつ
'hello'.split(''); // ['h', 'e', 'l', 'l', 'o']
// 空文字列で結合
['h', 'i'].join(''); // 'hi'
split('') で1文字ずつ分けると、ASCII以外の文字(絵文字など)で壊れることがあります。絵文字や漢字まで安全に分けるには、[...s] (spread)や Array.from(s) を使います。
const s = 'a😀b';
s.split(''); // ['a', '\uD83D', '\uDE00', 'b'] ← 壊れる
[...s]; // ['a', '😀', 'b']
Array.from(s); // ['a', '😀', 'b']
テンプレートリテラル — バッククォートの真価 #
+ で文字列を連結する場面は、ほぼすべてバッククォートのほうがすっきりします。
const name = 'カーティス';
const age = 30;
// + 演算
const a = 'こんにちは、' + name + ' (' + age + ')';
// テンプレートリテラル
const b = `こんにちは、${name} (${age})`;${...} の中にはどんな式でも入れられます。
const items = ['りんご', 'バナナ', 'ぶどう'];
`合計 ${items.length}個`;
`最初: ${items[0]}`;
`合計: ${1 + 2 + 3}`;
`状態: ${age >= 18 ? '成人' : '未成年'}`;複数行の文字列 #
const html = `
<div>
<h1>タイトル</h1>
<p>本文</p>
</div>
`;昔は '<div>\n<h1>...' のように \n で改行を直接書いていました。バッククォートなら、改行がそのまま入ります。
Tagged Template — 関数呼び出し #
少し高度な使い方です。バッククォートの前に関数を置くと、テンプレートがその関数の引数として渡されます。
function highlight(strings, ...values) {
return strings.reduce((acc, s, i) => {
return acc + s + (values[i] !== undefined ? `[${values[i]}]` : '');
}, '');
}
const name = 'カーティス';
const age = 30;
highlight`名前は ${name}、年齢は ${age} です`;
// '名前は [カーティス]、年齢は [30] です'
html のようなライブラリで、SQL/HTMLインジェクションを防ぐためによく使われるパターンです。最初は馴染みがなくても大丈夫です — 出会ったときに改めて詳しく見れば十分です。
数値 / 文字列の変換 #
String(42); // '42'
(42).toString(); // '42'
`${42}`; // '42' — 最もよくある慣用句
Number('42'); // 42
parseInt('42px'); // 42 — 先頭部分のみ
parseFloat('3.14'); // 3.14
+'42'; // 42 — 単項 + 演算子
Number('abc'); // NaN
parseInt('abc'); // NaN
Number(...) は全体が数値でなければ NaN になります。parseInt/parseFloat は 先頭から可能な分だけ パースします。入力に 42px のような単位が付いている場合は、後者が向いています。
正規表現 — パターンマッチング #
/パターン/フラグ の形のリテラルです。
const re = /hello/i; // 大文字小文字無視
'Hello World'.match(re); // ['Hello', ...]
re.test('Hi'); // false
re.test('Hello'); // true
よく使うメタ文字 #
| パターン | 意味 |
|---|---|
. | 任意の1文字 |
\d | 数字 |
\w | 単語文字(アルファベット / 数字 / _) |
\s | 空白 |
^ / $ | 行の先頭 / 末尾 |
+ | 1回以上 |
* | 0回以上 |
? | 0回または1回 |
[abc] | a, b, cのいずれか |
(...) | キャプチャグループ |
よく使う場面 #
// メール形式をざっくり検査
/^[^@]+@[^@]+\.[^@]+$/.test('me@example.com'); // true
// 数字だけ抽出
'price: 1500円'.match(/\d+/); // ['1500', ...]
// すべてのマッチ
'a1 b2 c3'.matchAll(/[a-z]\d/g); // イテラブル
// 置換
'2026-05-04'.replace(/-/g, '/'); // '2026/05/04'
g フラグは すべてのマッチ を探すという意味(global)です。なければ最初の1つだけを探します。
キャプチャグループ #
const date = '2026-05-04';
const m = date.match(/^(\d{4})-(\d{2})-(\d{2})$/);
// m: ['2026-05-04', '2026', '05', '04', ...]
const [, year, month, day] = m;
console.log(year, month, day); // 2026 05 04
丸括弧 (...) の中の部分が キャプチャ されて結果の配列に一緒に入ります。名前付きグループも可能です。
const m = '2026-05-04'.match(
/^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})$/
);
m.groups.year; // '2026'
m.groups.month; // '05'
m.groups.day; // '04'
(?<名前>...) の形です。結果の groups から名前で取り出します。
正規表現が必要なとき / 不要なとき #
正規表現は強力ですが、読みづらくなりやすい です。次の場合は、正規表現より通常の文字列メソッドのほうがほぼ常に良いです。
// 単純検索
s.includes('foo'); // O
s.match(/foo/); // X (過剰)
// 開始/終了の検査
s.startsWith('http'); // O
s.match(/^http/); // X
// 単純置換
s.replaceAll('foo', 'bar'); // O
s.replace(/foo/g, 'bar'); // X (過剰)
正規表現が輝くのは、パターンが可変だったり、キャプチャが必要な場合 — 日付やメールのような形式の検査、ログのパースなどです。
まとめ #
今回の記事で整理した内容:
- 引用符の3種類 —
'/"は意味が同じ、`はテンプレートリテラル - よく使うメソッド —
length/at/includes/slice/split/join/replaceAll - Unicodeで安全な分割は
[...s]またはArray.from(s) - テンプレートリテラル —
${}の中に式、複数行の文字列 - 変換 —
String()/Number()/parseInt()、+値の慣用句 - 正規表現の基本 — メタ文字、
gフラグ、キャプチャグループ - 単純な検索・置換は、正規表現よりメソッドのほうが明確
次の記事(#7 モジュール)ではシリーズの最後に — コードを複数のファイルに分けるES Modules、import/export のパターンを整理します。