charCodeAt() と codePointAt() は、どちらも文字列の指定位置にある文字を数値として見るメソッドです。ただし、返す単位が違います。
一言でいうと
charCodeAt() はUTF-16コード単位を返し、codePointAt() はUnicodeコードポイントを返せます。
比較表
| メソッド | 返すもの | 注意 |
|---|---|---|
charCodeAt(index) | UTF-16コード単位 | 絵文字などを分割する |
codePointAt(index) | Unicodeコードポイント | サロゲートペアをまとめて読める |
英数字や多くの日本語では、両者の違いが見えにくいです。絵文字などを扱うと違いが出ます。
普通の文字では同じに見える
const text = "A";
console.log(text.charCodeAt(0).toString(16)); // 41
console.log(text.codePointAt(0).toString(16)); // 41
A はU+0041なので、どちらも同じように見えます。
日本語でも同じに見えることが多い
const text = "あ";
console.log(text.charCodeAt(0).toString(16)); // 3042
console.log(text.codePointAt(0).toString(16)); // 3042
あ はU+3042で、UTF-16コード単位1つで表せるため、ここでも同じに見えます。
絵文字では違いが出る
const emoji = "😀";
console.log(emoji.length); // 2
console.log(emoji.charCodeAt(0).toString(16));
console.log(emoji.charCodeAt(1).toString(16));
console.log(emoji.codePointAt(0).toString(16));
charCodeAt() は前半と後半のコード単位を別々に返します。一方、codePointAt(0) は絵文字のコードポイントを返せます。
使い分け
| やりたいこと | 使うもの |
|---|---|
| ASCII範囲を高速に見る | charCodeAt() |
| UTF-16コード単位を見たい | charCodeAt() |
| 絵文字などのコードポイントを見たい | codePointAt() |
| 文字列をコードポイント単位で回したい | for...of と codePointAt() |
全角・半角のようにBMP内の範囲だけを見る処理では charCodeAt() でも扱いやすいです。
codePointAtにも注意はある
codePointAt() を使えば、すべての見た目の文字を完璧に1文字として扱えるわけではありません。
たとえば、複数のコードポイントが組み合わさって1つの絵文字に見える場合があります。人間の見た目の1文字まで正確に扱うには、Intl.Segmenterなど別の考え方が必要になることがあります。
よくある誤解
| 誤解 | 実際 |
|---|---|
charCodeAt() はUnicodeコードポイントを返す | UTF-16コード単位を返します |
codePointAt() なら文字数問題は全部解決 | 見た目の1文字とは別問題があります |
絵文字も length は1 | 多くの場合2以上になります |
charCodeAt() は古いので使わない | 範囲判定では今でも使えます |
まとめ
charCodeAt() はUTF-16コード単位、codePointAt() はUnicodeコードポイントを返します。ASCIIや半角カタカナの範囲判定では charCodeAt() が使いやすく、絵文字などを意識する場合は codePointAt() を検討します。
参考リソース
- MDN: String.prototype.charCodeAt()
- MDN: String.prototype.codePointAt()
- MDN: Unicode code point escapes