【JavaScript】文字コードを取得・変換する方法|charCodeAt・codePointAt・fromCharCode・fromCodePoint・サロゲートペアまで解説

JavaScript で文字と文字コード(数値)を相互に変換する操作は、入力値の文字種判定、暗号処理、全角半角変換など幅広い場面で必要になります。この記事では charCodeAt / codePointAt(文字→コード)と fromCharCode / fromCodePoint(コード→文字)の 4 メソッドを整理し、サロゲートペアの問題と実務パターンまで解説します。

この記事でわかること
・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 — コードポイントから文字を生成する

fromCodePointfromCharCode の 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!"

関連記事

よくある質問

QcharCodeAt と codePointAt はどちらを使えばよいですか?
AASCII やひらがな・カタカナなど BMP 内の文字だけを扱う場合は charCodeAt で十分です。絵文字や BMP 外の漢字を扱う可能性がある場合は codePointAt を使ってください。迷ったら codePointAt の方が安全です。
Q文字コードから文字を生成するには?
AString.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 を使い分けてください。