【実務・中級編】 静的メソッド(String.fromCharCode, String.fromCodePoint) – JavaScript実践ガイド

Stringの静的メソッドを制する:fromCharCodeとfromCodePointの「深淵なる違い」

フロントエンドの現場で「文字コードから文字列を生成する」という処理、意外と遭遇しますよね。アイコンフォントの生成、暗号化処理のデコード、あるいは特定のバイナリデータをパースする際など。

多くの開発者が `String.fromCharCode` で何となく済ませてしまっていますが、実はそこに「歴史的負債」と「現代的な解決策」の境界線が隠れています。今回は、中級エンジニアが絶対に知っておくべき `String.fromCharCode` と `String.fromCodePoint` の決定的な違いと、なぜ後者を使うべきなのかを深掘りします。

—

1. String.fromCharCodeの「古き良き限界」

`String.fromCharCode` は、JavaScriptの黎明期から存在するメソッドです。UTF-16のコードユニットを指定して文字列を組み立てます。

// A, B, C という文字列を作る
const str = String.fromCharCode(65, 66, 67);
console.log(str); // “ABC”

シンプルですね。しかし、ここで問題になるのが「サロゲートペア」です。

JavaScriptの文字列はUTF-16で表現されています。初期のUnicodeは16ビット(65,536文字分)で収まると考えられていましたが、絵文字などの特殊文字が増えるにつれ、16ビット(コードユニット)を2つ組み合わせて1文字を表現する「サロゲートペア」という仕組みが必要になりました。

`fromCharCode` は、16ビット単位でしか処理ができません。そのため、サロゲートペアが必要な文字(例えば「𠮷」のような漢字や、最新の絵文字)を扱うと、途端に壊れます。

// 「𠮷」はコードポイント 0x20BB7。
// fromCharCode で扱おうとすると…
console.log(String.fromCharCode(0x20BB7)); // 期待値とは異なる文字(0x0BB7に切り捨てられる)

現場のバグ調査で「なぜか絵文字が文字化けする」「特殊な漢字だけ検索にヒットしない」というケースの多くは、この古いメソッドが原因だったりします。

—

2. fromCodePointで「現代の常識」をインストールする

ES2015(ES6)で導入された `String.fromCodePoint` は、まさにこのサロゲートペア問題を解決するために生まれてきました。

こいつは引数に「コードポイント(Unicodeの論理的な番号)」を直接渡せます。内部で自動的にサロゲートペアが必要かどうかを判断し、適切なビット列に変換してくれるのです。

/

  • 実践的な比較:絵文字「🚀」を出力してみる

/
const emojiCode = 0x1F680;

// × fromCharCodeだと…
console.log(String.fromCharCode(emojiCode)); // 謎の記号が出力される

// ◎ fromCodePointなら!
console.log(String.fromCodePoint(emojiCode)); // “🚀” が正しく表示される

なぜこれが重要なのか?

ブラウザのエンジン(V8など)の裏側を覗くと、`fromCodePoint` は入力された数値をチェックし、それがBMP(基本多言語面)を超えているかどうかを計算しています。もし超えていれば、適切に上位サロゲートと下位サロゲートに分割してメモリに展開する――という複雑な処理を、私たちが意識することなく一瞬で実行してくれています。

—

3. 実務で使えるベストプラクティス

現場でこの知識をどう活用すべきか? 結論はシンプルです。「文字コードから文字列を作るなら、例外なく `fromCodePoint` を使うこと」。

特に、外部APIから取得した数値配列を文字列に復元したり、動的にDOMのコンテンツを生成するシーンでは、迷わずこちらを選んでください。

以下は、配列として受け取ったコードポイント群を安全に文字列化する、実用的なユーティリティ関数の例です。

/

  • 数値配列から安全に文字列を生成する堅牢な関数
  • @param {number[]} codePoints
  • @returns {string}

/
function createStringFromPoints(codePoints) {
try {
// スプレッド演算子で展開して渡すのが現代的
return String.fromCodePoint(…codePoints);
} catch (e) {
console.error(“無効なコードポイントが含まれています:”, e);
return “”;
}
}

// 使用例
const codes = [72, 101, 108, 108, 111, 32, 0x1F30D]; // “Hello 🌍”
console.log(createStringFromPoints(codes));

—

最後に:シニアからのアドバイス

「動けばいい」というコードは、数ヶ月後の自分やチームメンバーを確実に苦しめます。特に文字列操作は、後から「特定の環境でだけ文字化けする」といった、再現性の低い地獄のようなバグを生みやすい領域です。

JavaScriptの歴史的な経緯を知ることは、単なる知識の蓄積ではありません。「なぜ今の仕様になっているのか」という設計思想への理解です。

これからは `fromCharCode` を見かけたら、「お、ここは歴史的な遺産だな。現代的な `fromCodePoint` に置き換えておこう」とリファクタリングの対象として捉えてみてください。その小さな積み重ねが、堅牢なアプリケーションを作る唯一の近道です。

さあ、明日からのコーディングで、コードの「質」を一段階引き上げていきましょう!

コメント

タイトルとURLをコピーしました