サロゲートペア:BMP外の文字

基本多言語面の外の文字がUTF-16でサロゲートペアを使用する方法と、JavaScriptの.lengthが1文字に対して2を返す理由を学びます。

Multi-byte Characters

詳細な説明

UTF-16のサロゲートペア

基本多言語面(BMP)にはUnicodeコードポイントU+0000からU+FFFFが含まれます。この範囲外の文字(補助面)は単一の16ビットコードユニットに収まらないため、UTF-16はサロゲートペア(2つの16ビットコードユニットの組み合わせ)としてエンコードします。

サロゲートペアの仕組み

U+1F600(😀 Grinning Face)の場合:

  1. 0x10000を引く:0x1F600 - 0x10000 = 0xF600
  2. 上位サロゲート:0xD800 + (0xF600 >> 10) = 0xD83D
  3. 下位サロゲート:0xDC00 + (0xF600 & 0x3FF) = 0xDE00

JavaScriptは2つのコードユニットとして保存:\uD83D\uDE00

JavaScript .lengthへの影響

"😀".length          // 2  (サロゲートペア)
[..."😀"].length     // 1  (コードポイント)
"😀".codePointAt(0)  // 128512 (U+1F600)

サロゲートペアを使用する文字

カテゴリ 範囲
絵文字 U+1F600–U+1FAFF 😀 🚀 🍕
数学記号 U+1D400–U+1D7FF 𝐀 𝐁 𝐂
音楽記号 U+1D100–U+1D1FF 𝄞
歴史的文字 U+10000–U+1007F 𐀀
CJK拡張B+ U+20000–U+2A6FF 珍しい漢字

壊れる文字列操作

一般的な文字列操作はサロゲートペアを破壊する可能性があります:

// 間違い:サロゲートペアを分割する可能性
str.substring(0, 1)  // 上位サロゲートのみを返す可能性
str.charAt(0)        // 上位サロゲートのみを返す

// 正しい:コードポイント対応のメソッドを使用
[...str].slice(0, 1).join("")

バイトサイズ

エンコーディング サロゲートペア文字あたりのバイト数
UTF-8 4バイト
UTF-16 4バイト(2コードユニット × 2バイト)
UTF-32 4バイト(常に)

興味深いことに、補助文字ではすべてのエンコーディングが同じ4バイトを使用します。違いはBMP文字でのみ重要です。

ユースケース

絵文字や珍しい文字を含む文字列を操作するJavaScriptアプリケーションを構築する際、サロゲートペアを理解することは、部分文字列操作、データベースストレージ、APIペイロード処理中のデータ破損を防ぐために不可欠です。

試してみる — String Length Calculator

フルツールを開く