JavaScript で文字と文字コード(数値)を相互に変換する操作は、入力値の文字種判定、暗号処理、全角半角変換など幅広い場面で必要になります。この記事では charCodeAt / codePointAt(文字→コード)と fromCharCode / fromCodePoint(コード→文字)の 4 メソッドを整理し、サロゲートペアの問題と実務パターンまで解説します。
この記事でわかること
・charCodeAt で UTF-16 コードを取得する方法
・codePointAt で Unicode コードポイントを取得する方法
・String.fromCharCode でコードから文字を生成する方法
・String.fromCodePoint でコードポイントから文字を生成する方法
・charCodeAt と codePointAt の違い(サロゲートペア問題)
・大文字小文字判定・シーザー暗号・全角半角変換の実務パターン
・charCodeAt で UTF-16 コードを取得する方法
・codePointAt で Unicode コードポイントを取得する方法
・String.fromCharCode でコードから文字を生成する方法
・String.fromCodePoint でコードポイントから文字を生成する方法
・charCodeAt と codePointAt の違い(サロゲートペア問題)
・大文字小文字判定・シーザー暗号・全角半角変換の実務パターン
文字コード変換メソッドの全体像
| 方向 | メソッド | 範囲 | サロゲートペア |
|---|---|---|---|
| 文字 → コード | charCodeAt(i) |
0〜65535(UTF-16) | 半分のコードを返す |
| 文字 → コード | codePointAt(i) |
0〜1114111(Unicode) | 正しいコードポイントを返す |
| コード → 文字 | String.fromCharCode(n) |
0〜65535 | サロゲートペアを直接生成できない |
| コード → 文字 | String.fromCodePoint(n) |
0〜1114111 | 絵文字も正しく生成できる |
ASCII やひらがな・カタカナなど基本多言語面(BMP: U+0000〜U+FFFF)の文字であれば、charCodeAt / fromCharCode で十分です。絵文字や一部の漢字など BMP 外の文字を扱う場合は codePointAt / fromCodePoint を使ってください。
charCodeAt — 文字から UTF-16 コードを取得する
構文
const code = str.charCodeAt(index); // index: 文字の位置(0始まり) // 戻り値: UTF-16 コードユニット(0〜65535 の整数) // 範囲外の場合は NaN
基本例
console.log("A".charCodeAt(0)); // 65
console.log("a".charCodeAt(0)); // 97
console.log("0".charCodeAt(0)); // 48
console.log("あ".charCodeAt(0)); // 12354
// 複数文字の文字列
const str = "Hello";
console.log(str.charCodeAt(0)); // 72("H")
console.log(str.charCodeAt(4)); // 111("o")
よく使う文字コードの範囲
| 文字種 | 範囲 | コード |
|---|---|---|
| 数字 0-9 | "0"〜"9" |
48〜57 |
| 英大文字 A-Z | "A"〜"Z" |
65〜90 |
| 英小文字 a-z | "a"〜"z" |
97〜122 |
| ひらがな | "ぁ"〜"ん" |
12353〜12435 |
| カタカナ | "ァ"〜"ン" |
12449〜12531 |
codePointAt — Unicode コードポイントを取得する
codePointAt は charCodeAt と似ていますが、サロゲートペアを正しく処理して完全な Unicode コードポイントを返します。
JavaScript
// BMP の文字: charCodeAt と同じ結果
console.log("A".codePointAt(0)); // 65
console.log("あ".codePointAt(0)); // 12354
// サロゲートペア(絵文字): 結果が異なる
const emoji = "?";
console.log(emoji.charCodeAt(0)); // 55357(上位サロゲートのみ)
console.log(emoji.codePointAt(0)); // 128512(正しいコードポイント)
charCodeAt は UTF-16 コードユニット単位で値を返すため、サロゲートペアの場合は上位サロゲート(前半)のコードしか取得できません。絵文字や BMP 外の文字を扱う場合は必ず codePointAt を使いましょう。
String.fromCharCode — コードから文字を生成する
構文
const char = String.fromCharCode(code1, code2, ...); // 引数: UTF-16 コードユニット(0〜65535)を1つ以上 // 戻り値: 対応する文字を連結した文字列
基本例
// 1文字ずつ console.log(String.fromCharCode(65)); // "A" console.log(String.fromCharCode(12354)); // "あ" // 複数のコードをまとめて文字列に console.log(String.fromCharCode(72, 101, 108, 108, 111)); // "Hello"
String.fromCodePoint — コードポイントから文字を生成する
fromCodePoint は fromCharCode の Unicode 対応版で、BMP 外の文字(絵文字など)も正しく生成できます。
JavaScript
// BMP の文字: fromCharCode と同じ結果 console.log(String.fromCodePoint(65)); // "A" console.log(String.fromCodePoint(12354)); // "あ" // サロゲートペア: fromCodePoint なら正しく生成できる console.log(String.fromCodePoint(128512)); // "?" // fromCharCode では生成できない(サロゲートペアを分割して渡す必要がある) console.log(String.fromCharCode(55357, 56832)); // "?"(冗長)
fromCharCode と fromCodePoint の使い分け
| 比較項目 | fromCharCode | fromCodePoint |
|---|---|---|
| 入力範囲 | 0〜65535 | 0〜1114111 |
| 絵文字の生成 | サロゲートペアを分割して渡す必要あり | コードポイント1つで OK |
| ブラウザ対応 | ES1(全ブラウザ) | ES2015(IE 非対応) |
charCodeAt と codePointAt の違い(サロゲートペア)
BMP 内の文字では両者は同じ値を返しますが、サロゲートペアの文字では結果が異なります。
JavaScript
const str = "A?B"; // "A" (index 0): BMP文字 → 同じ結果 console.log(str.charCodeAt(0)); // 65 console.log(str.codePointAt(0)); // 65 // "?" (index 1-2): サロゲートペア → 異なる結果 console.log(str.charCodeAt(1)); // 55357(上位サロゲート) console.log(str.codePointAt(1)); // 128512(正しいコードポイント) // "B" の位置にも注意 console.log(str.charCodeAt(3)); // 66("B"はindex 3) console.log(str[3]); // "B"
サロゲートペアは内部的に 2 つのインデックスを占めるため、"A?B" の "B" はインデックス 3 にあります(2 ではない)。文字単位でループするには for...of が最適です。
文字単位のコードポイント一覧を取得
const str = "A?B";
// for...of はサロゲートペアを正しく1文字として扱う
for (const char of str) {
console.log(char, char.codePointAt(0));
}
// "A" 65
// "?" 128512
// "B" 66
実務でよく使うパターン
文字種の判定(大文字・小文字・数字)
JavaScript
function charType(char) {
const code = char.charCodeAt(0);
if (code >= 65 && code <= 90) return "uppercase";
if (code >= 97 && code <= 122) return "lowercase";
if (code >= 48 && code <= 57) return "digit";
return "other";
}
console.log(charType("A")); // "uppercase"
console.log(charType("z")); // "lowercase"
console.log(charType("5")); // "digit"
console.log(charType("あ")); // "other"
シーザー暗号(文字をN文字ずらす)
JavaScript
function caesarCipher(text, shift) {
return [...text].map(char => {
const code = char.charCodeAt(0);
// 大文字 A-Z
if (code >= 65 && code <= 90) {
return String.fromCharCode(((code - 65 + shift) % 26) + 65);
}
// 小文字 a-z
if (code >= 97 && code <= 122) {
return String.fromCharCode(((code - 97 + shift) % 26) + 97);
}
// その他はそのまま
return char;
}).join("");
}
console.log(caesarCipher("Hello, World!", 3)); // "Khoor, Zruog!"
console.log(caesarCipher("Khoor, Zruog!", 23)); // "Hello, World!"(復号)
全角英数字を半角に変換する
JavaScript
function toHalfWidth(str) {
return str.replace(/[A-Za-z0-9]/g, char => {
return String.fromCharCode(char.charCodeAt(0) - 0xFEE0);
});
}
console.log(toHalfWidth("Hello123")); // "Hello123"
全角英数字と半角英数字のコードポイントは
0xFEE0(65248)の差があります。この差分を引くだけで半角に変換できます。逆に足せば半角→全角変換も可能です。アルファベットの配列を生成する
JavaScript
// A-Z の配列
const alphabet = Array.from({ length: 26 }, (_, i) =>
String.fromCharCode(65 + i)
);
console.log(alphabet); // ["A", "B", "C", ... "Z"]
// a-z の配列
const lowerAlphabet = Array.from({ length: 26 }, (_, i) =>
String.fromCharCode(97 + i)
);
console.log(lowerAlphabet); // ["a", "b", "c", ... "z"]
制御文字を検出・除去する
JavaScript
function removeControlChars(str) {
return [...str].filter(char => {
const code = char.codePointAt(0);
// 制御文字: 0-31, 127
return !(code <= 31 || code === 127);
}).join("");
}
const dirty = "Hello\x00World\x1F!";
console.log(removeControlChars(dirty)); // "HelloWorld!"
関連記事
- Unicode コードポイントを取得する方法 — charCodeAt・codePointAt の詳細比較
- ASCII コードを文字列に変換する方法 — fromCharCode の詳細と暗号実装
- サロゲートペア文字列を正しく扱う方法 — for-of・スプレッド構文・正規表現 u フラグ
- charAt の使い方 — 文字列から 1 文字を取得する方法
- 文字列の大文字・小文字を変換する方法
- 機種依存文字・特殊文字のチェックと除去方法
よくある質問
QcharCodeAt と codePointAt はどちらを使えばよいですか?
AASCII やひらがな・カタカナなど BMP 内の文字だけを扱う場合は
charCodeAt で十分です。絵文字や BMP 外の漢字を扱う可能性がある場合は codePointAt を使ってください。迷ったら codePointAt の方が安全です。Q文字コードから文字を生成するには?
A
String.fromCharCode(65) で "A" が生成されます。絵文字など BMP 外の文字は String.fromCodePoint(128512) で "?" のように生成できます。Q全角カタカナを半角カタカナに変換するには?
A全角カタカナと半角カタカナのコード差は一定ではなく、濁音・半濁音の扱いも異なるため単純な演算では変換できません。
str.normalize("NFKC") で半角カナを全角カナに統一する方法か、専用の変換テーブルを使うのが現実的です。QUnicode のエスケープシーケンスとは何ですか?
AJavaScript では
"\u0041"(4桁: BMP)や "\u{1F600}"(波括弧: 全範囲)で Unicode 文字を直接記述できます。"\u0041" は "A"、"\u{1F600}" は "?" と同じです。Q文字列内の文字が印字可能かどうか判定するには?
AASCII の印字可能文字はコード 32(スペース)〜 126(
~)の範囲です。Unicode を含む判定には正規表現 /\p{Cc}/u(制御文字カテゴリ)を使うと厳密に判定できます。まとめ
JavaScript で文字と文字コードを相互変換する 4 つのメソッドを整理しました。
- 文字 → コード:
charCodeAt(UTF-16)/codePointAt(Unicode) - コード → 文字:
String.fromCharCode(UTF-16)/String.fromCodePoint(Unicode) - サロゲートペア: 絵文字には codePointAt / fromCodePoint を使う
文字種判定、シーザー暗号、全角半角変換、アルファベット配列生成など、文字コード操作は実務で意外と出番が多いテクニックです。BMP 内で完結する処理なら charCodeAt / fromCharCode で十分ですが、絵文字対応が必要な場面では codePointAt / fromCodePoint を使い分けてください。