こんにちは!フロントエンドの現場を渡り歩いてきたチーフアーキテクトの私です。
JavaScriptで文字列を扱っていると、なんだか文字化けしたり、文字数が変にズレたりして「ぐぬぬ……」となった経験、ありませんか? 大丈夫ですよ、それ、あなたが悪いわけじゃありません。コンピュータの世界が、私たちの使っている日本語や絵文字にちょっと意地悪なだけなんです。
今回は、そんな文字まわりのトラブルをスマートに解決してくれる、ちょっと玄人好みなけれど実はすごく優しいメソッド`String.prototype.codePointAt()`について、一緒に紐解いていきましょう!
—
そもそも「文字」って、コンピュータの中ではどうなっているの?
いきなりコードを書く前に、ちょっとだけコンピュータの気持ちになってみましょう。
コンピュータは、実は「文字」そのものを理解できません。すべて「数字」で覚えています。「あ」はこの番号、「A」はこの番号、というふうに、世界中の文字に番号(これをコードポイントと呼びます)が振られているんです。
普段、私たちがJavaScriptで文字コードを調べるときによく使うのが `charCodeAt()` というメソッド。
「よし、この文字の番号を教えてくれ!」と頼むと、番号を答えてくれます。
……普通はこれでハッピーエンドなのですが、世の中には「通常の番号枠(1文字分)には収まりきらない、ビッグサイズな文字たち」が存在します。そう、みんな大好き絵文字や、歴史の教科書に出てくるような珍しい漢字(環境依存文字)です。
—
巨人あらわる!「サロゲートペア」という厄介な仕組み
ここで登場するのが、JavaScript(というかJavaScriptが生まれた大昔のUnicode規格)のちょっとした歴史的おまけ、サロゲートペアです。
お買い物の例えで考えてみましょう。
普通の文字は、1文字につき「お弁当箱1つ(16ビット)」にぴったり収まります。
でも、絵文字などのビッグな文字は、お弁当箱1つには入りきりません。そこで、「2つのお弁当箱をコンビで使って、やっと1つの文字を表現する」という裏技を使います。これがサロゲートペアです。
このコンビでやってくる文字に対して、昔ながらの `charCodeAt()` を使うとどうなるか?
なんと、「コンビの片割れ(前半のお弁当箱の中身)」だけを覗き見して、本当の文字の番号とは違う、中途半端な数字を返しちゃうんです。「あれ? 頼んだのと違う数字が出てきたぞ……?」と、ここで多くの開発者が頭を抱えることになります。
—
救世主登場! `codePointAt()` の出番です
そこで今回の主役、`codePointAt()` の登場です。
このメソッドは、いわば「お弁当箱がコンビ(サロゲートペア)だろうが何だろうが、そんなの関係ねぇ! 正しい全体の番号(Unicodeコードポイント)を一発で見つけ出してやるぜ!」という、非常に頼りになるベテランの番頭さんです。
百聞は一見にしかず。実際にコードを動かして、その違いをこの目で確かめてみましょう。
実践!コードで違いを見てみよう
お手元のエディタやブラウザのコンソールに、以下のコードをそのまま貼り付けて試してみてください。
// 例として、みんな大好き「笑顔の猫」の絵文字( 😸 )を使います。
// この絵文字は、コンピュータの中では2つのお弁当箱(サロゲートペア)でできています。
const catEmoji = ‘😸’;
// 1. 昔ながらの charCodeAt() で覗いてみる
console.log(‘— charCodeAt の場合 —‘);
console.log(catEmoji.charCodeAt(0)); // 前半のお弁当箱の数字(中途半端!)
console.log(catEmoji.charCodeAt(1)); // 後半のお弁当箱の数字(これまた中途半端!)
// 2. codePointAt() で正しく覗いてみる
console.log(‘— codePointAt の場合 —‘);
console.log(catEmoji.codePointAt(0).toString(16)); // おお!正しいUnicodeの16進数(1f638)が出てきた!
`codePointAt(0)` を使うと、コンビのどちら側から覗こうとも、その文字が持っている「本当の戸籍番号(コードポイント)」を正確に引っ張り出してくれます。末尾の `.toString(16)` は、人間が見慣れたUnicodeの形式(`U+1F638`など)に合わせるための魔法の呪文です。
—
どんなときにこのメソッドを使うの?
「理屈はわかったけど、普段のWeb制作でそんなビッグな文字、そんなに扱う?」と思われるかもしれません。
確かに、普通のブログ記事やコーポレートサイトのテキスト(「こんにちは」や「お問い合わせ」など)であれば、出番は多くありません。しかし、以下のような場面では必須の教養になります。
1. ユーザーが入力したSNSのプロフィールやコメント欄のチェック
- 今やユーザーは容赦なく絵文字を連打してきます。文字数制限をバリデーションする際、サロゲートペアを考慮しないと、絵文字1文字を「2文字」とカウントしてエラーになり、ユーザーをイライラさせてしまう原因になります。
2. 文字コードの変換ツールや、マイナーな漢字を扱うシステムを作る時
- 戸籍システムや自治体のサービス、古い人名漢字などを扱うWebアプリでは、JIS第3水準・第4水準といった特殊な漢字がサロゲートペアとして登場します。ここで `charCodeAt` を使ってしまうと、文字化けやデータ破損の元になります。
—
まとめ:怖がらなくて大丈夫!
最初は「サロゲートペア? コードポイント?」と、聞き慣れない言葉に身構えてしまうかもしれません。でも、基本の考え方はこうです。
- 普通の文字なら、どっちのメソッドを使っても大体うまくいきます。
- 絵文字や珍しい漢字を正確に扱いたいときは、「あ、あいつはコンビだから、`codePointAt()` を使ってあげなきゃな」と思い出してあげてください。
JavaScriptは、こうした少し泥臭い文字の歴史を優しく包み込みながら進化してきた言語です。躓いたときは「コンピュータも一生懸命なんだな」と優しく見守りつつ、こうして正しいメソッドを一つずつ味方につけていけば大丈夫。
あなたのフロントエンドライフが、少しでも快適で楽しいものになりますように! 次回の記事でも、現場で使える実用的な知見をたっぷりお届けしますね。

コメント