【実務・中級編】 codePointAt() と charCodeAt() の使い分け – JavaScript実践ガイド

その「文字」は本当に1文字か? `codePointAt` と `charCodeAt` の深い闇と光

現場でバリバリとフロントエンドを書いていると、「文字列のバリデーションなんて楽勝だ」と思う瞬間があるよな。でもな、絵文字や特殊な記号、あるいは歴史的な遺産であるサロゲートペアが絡んだ途端、その自信は脆くも崩れ去る。

今日は、中級エンジニアなら絶対に押さえておくべき「文字コードの正体」と、`charCodeAt` から `codePointAt` への進化について、現場の泥臭い視点から解説するぜ。

—

なぜ `charCodeAt` だけでは不十分なのか

結論から言うと、`charCodeAt` は「UTF-16のコードユニット」を返すメソッドであり、「文字そのもの」を返しているわけではないからだ。

JavaScriptの歴史を振り返ると、ECMAScriptの初期設計では「すべての文字は16bit(2バイト)で収まる」と想定されていた。だが、現実は残酷だ。絵文字や古代文字など、16bitに収まらない文字(補助文字)が登場し、それらは「サロゲートペア」という仕組みを使って、2つの16bitコードユニットで1つの文字を表現することになった。

現場で遭遇する「バグの温床」

もしお前が「文字列の先頭の文字コードが何か」を判定する際、`charCodeAt(0)` を安直に使っているとしたら、それは地雷を踏んでいる可能性がある。

// 「𠮷」(つちよし:サロゲートペア文字)
const str = “𠮷”;

// charCodeAt(0) は最初の16bitしか見ないため、文字全体を特定できない
console.log(str.charCodeAt(0)); // 55362 (全体の正体ではない)

// 2つ目のコードユニットも必要になる
console.log(str.charCodeAt(1)); // 57271

このように、`charCodeAt` を使うと、1文字を判定するためにロジックが複雑化し、可読性もメンテナンス性も著しく低下する。

—

救世主 `codePointAt` の登場

ES2015(ES6)で導入された `codePointAt` は、この悲劇を解決するために生まれた。こいつは「サロゲートペアを考慮して、完全なコードポイント(Unicodeの論理的な値)」を返してくれる。

現場での使い分けの基準はシンプルだ。「文字単位でループしたり、正規化したりする必要があるなら、絶対に `codePointAt` を使え」。

実践的なサンプル:サロゲートペアを正しく扱う

以下のコードを見てくれ。これが現場で「文字をイテレートする」際の正しいアプローチだ。

/

  • 現場で使える!サロゲートペアを考慮した文字列操作の例

/
const text = “A𠮷B”;

// 1. charCodeAt を使うと文字が分割されてしまう
console.log([…text].map(char => char.charCodeAt(0)));
// 結果: [65, 55362, 66] ※ 55362 は「𠮷」の半分だけ

// 2. codePointAt を使えば、文字の論理値を正しく取得できる
for (let i = 0; i < text.length; i++) { const code = text.codePointAt(i); // codePointAt はサロゲートペアなら自動的に2つ分を読み取ってくれる // ただし、i はインデックスなので「次の文字」へ移動する際は注意が必要 console.log(`インデックス ${i} のコードポイント: ${code.toString(16)}`); // 4桁(基本多言語面)を超える文字(𠮷など)の場合、インデックスをスキップする工夫が必要 if (code > 0xFFFF) i++;
}

—

プロとしてのアドバイス:使い分けの指針

現場レベルでの判断基準を整理しておくぜ。

1. `charCodeAt` を使ってもいい場面

  • レガシーな環境との互換性:ブラウザのサポート状況が極端に古い場合(とはいえ、今どきは Babel や Polyfill があるから言い訳にはなりにくいが)。
  • 特定のインデックスのコードユニットを単に確認したいだけの場合:暗号処理や低レイヤーなバイナリ操作など、意図的にUTF-16の構造を触る場合。

2. `codePointAt` を使うべき場面

  • ユーザー入力のバリデーション:絵文字を含めた文字数制限や入力チェックを行う場合。
  • 文字列の変換・正規化:Unicodeの仕様に準拠した正確な処理が必要な場合。
  • モダンな開発すべて:現代のJavaScript開発において、サロゲートペアを無視していい理由はどこにもない。

—

まとめ:結局のところ「文字」とは何か

エンジニアとして覚えておいてほしいのは、「画面に見えている『文字』は、プログラム上の『1つのスロット』とは限らない」という事実だ。

`charCodeAt` はプログラムの都合に合わせた「メモリの断片」を見ているに過ぎない。一方で `codePointAt` は、Unicodeという国際的な規格に基づいた「意味のある文字」を捉えようとしている。

現場でバグを埋め込まないための鉄則は、「文字列を扱うときは、常にサロゲートペアの存在を疑え」だ。これさえ意識できていれば、お前が書くコードの信頼性はグッと上がる。

何かあったらまた聞いてくれ。現場の泥臭い苦労話なら、いつでも付き合うぜ。

コメント

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