Surrogate Pair
Cơ chế trong UTF-16 để biểu diễn ký tự ngoài BMP bằng hai đơn vị mã 16-bit.
Cặp thay thế là cơ chế trong mã hóa UTF-16 để biểu diễn ký tự ngoài Mặt phẳng đa ngôn ngữ cơ bản (BMP: U+0000 đến U+FFFF). Nó kết hợp một surrogate cao (U+D800 đến U+DBFF) và một surrogate thấp (U+DC00 đến U+DFFF) thành hai đơn vị mã 16-bit để biểu diễn một ký tự duy nhất. Khoảng một triệu ký tự trong phạm vi Unicode U+10000 đến U+10FFFF được biểu diễn bằng sơ đồ này.
Nhu cầu về cặp thay thế phát sinh từ lịch sử mở rộng của Unicode. Ban đầu, Unicode dự định chứa tất cả hệ thống chữ viết thế giới trong 16 bit (65.536 ký tự), nhưng việc bổ sung ký tự biến thể CJK, chữ viết lịch sử và emoji cho thấy 16 bit là không đủ. Do đó UTF-16 dành riêng một phạm vi BMP chưa sử dụng (U+D800 đến U+DFFF) cho surrogate, giới thiệu biểu diễn hai đơn vị mã. Sách xử lý emoji JavaScript đề cập đến phương pháp đếm chính xác.
Most emoji are located outside the BMP and are represented as surrogate pairs. For example, "😀" (U+1F600) is represented by high surrogate U+D83D and low surrogate U+DE00. JavaScript's String.length returns the number of UTF-16 code units, so the length of "😀" is 2, not 1. Similarly, charAt() and charCodeAt() hoạt động ở cấp đơn vị mã và không thể xử lý chính xác ký tự cặp thay thế.
Để có số ký tự chính xác, sử dụng [...str].length or Array.from(str).length. Các phương pháp này tận dụng giao thức iterator để phân tách chuỗi theo code point, coi cặp thay thế là ký tự đơn. Từ ES2015, codePointAt() and for...of cũng hoạt động ở cấp code point. Tuy nhiên, để đếm chính xác cụm grapheme (ký tự trực quan gồm ký tự kết hợp hoặc chuỗi ZWJ) cần Intl.Segmenter API.
Cặp thay thế chỉ có trong UTF-16 và không tồn tại trong UTF-8 hoặc UTF-32. UTF-8 mã hóa trực tiếp code point bằng chuỗi có độ dài thay đổi (1 đến 4 byte), trong khi UTF-32 sử dụng cố định 4 byte cho tất cả code point. Cột ký tự cơ sở dữ liệu (như sự khác biệt giữa utf8 and utf8mb4của MySQL) cũng có thể gặp vấn đề khi lưu trữ ký tự cặp thay thế. Sách bảng mã ký tự cung cấp giải thích kỹ thuật chi tiết về cặp thay thế.
Từ góc độ đếm ký tự, cặp thay thế đặt ra câu hỏi cơ bản về điều gì tạo thành "một ký tự." Kết quả khác nhau tùy thuộc vào việc bạn đếm đơn vị mã UTF-16, code point hay cụm grapheme. Khi thiết kế công cụ đếm ký tự, điều quan trọng là xác định rõ đơn vị đếm và đảm bảo nó phù hợp với kỳ vọng của người dùng.