charCodeAt と codePointAt の違いとサロゲートペアの扱いについて

絵文字などのサロゲートペアを使う文字は、charCodeAt で Unicode のコードポイントをうまく取得できません。

const letter = '😀'

const code0 = letter.charCodeAt(0).toString(16)
const code1 = letter.charCodeAt(1).toString(16)

console.log(code0, code1)
// d83d de00

絵文字などのを含む、Unicode に新しく追加された多くの記号は、二つのコードポイントで表現されています。

そのため😀は一個の文字であるにもかかわらず、charCodeAt(1) で de00 が得られています。

😀 = d83d de00

これをサロゲートペアsurrogate pairといい、最初のコードポイントを high surrogate、次のコードポイントを low surrogate といいます。

codePointAt

以下はわかりやすさを重視した解説で、正確さに欠ける可能性があります。

😀は二つのコードポイントで表現されますが、UTF-16 ではこれを一つのコードポイントでも表現します。

😀 = d83d de00
😀 = 1f600

1f600 は codePointAt で取得します。

const letter = '😀'

const codePoint = letter.codePointAt(0).toString(16)

console.log(codePoint)
// 1f600

二つの関数は次のようにまとめられます。

charCodeAt

普通の文字はコードポイントを返す。

絵文字など、二つのコードポイントで表現されるサロゲートペアの文字は想定どおりの結果を返さない……かもしれない。

codePointAt

普通の文字だろうが、サロゲートペアだろうが、一つのコードポイントを返す。

サロゲートペアそのものがほしいときは charCodeAt を使い、一つのコードポイントをいかなる文字でもシンプルに取得したいときは codePointAt を使います。