Appearance
将字符串转换为16进制字符编码
本节目标:理解“将字符串转换为16进制字符编码”的核心思路,并能把它用于实际开发或面试表达。 对于 JavaScript 的 charCodeAt() 方法,它会返回表示给定字符串中的指定字符的 UTF-16 编码的数字。UTF-16 能够涵盖 Unicode 基本多文本平面(Basic Multilingual Plane, BMP)中的所有字符,包括大多数常用的字符和符号。对于 BMP 之外的字符(包括一些非常罕见的汉字),它们被编码为一对“代理对”(surrogate pair)。
因此,如果你处理的字符串只包含 BMP 内的字符(U+0000 到 U+FFFF),charCodeAt() 将工作得很好。
但是,如果你的字符串可能包含 BMP 之外的字符(即 U+010000 到 U+10FFFF),你需要使用更复杂的逻辑来正确地处理这些字符。
以下是一个例子,演示如何处理可能包含整个 Unicode 范围内字符的字符串: strToHexCharCode: function(str) { if (str === "") return ""; let hexCharCode = []; for (let i = 0; i < str.length; i++) { let code = str.codePointAt(i); if (code > 0xFFFF) { i++; // 跳过代理对的第二个部分 } hexCharCode.push(code.toString(16)); } return hexCharCode.join("").toUpperCase(); } 在这个版本中,我使用了 codePointAt() 而不是 charCodeAt()。codePointAt() 返回一个 Unicode 代码点,能够正确地处理整个 Unicode 范围(包括代理对)。如果遇到一个代理对,codePointAt() 会返回一个大于 0xFFFF 的代码点,并且我会增加 i 的值以跳过代理对的第二个部分。 这样,这个函数就能正确地处理包括非常罕见的汉字和特殊字符在内的所有 Unicode 字符了。
对于 UTF-16 编码中的“代理对”(surrogate pairs),第一个代码单元(high surrogate)和第二个代码单元(low surrogate)总是紧密配对出现的。在 JavaScript 字符串中,这样的配对应当是合法和完整的。
因此,在遇到高代理(high surrogate)并且用 codePointAt() 获取了完整的 Unicode 代码点之后,跳过低代理(low surrogate)通常是安全的,因为低代理本身并不代表一个有效的字符,而仅仅是和高代理一起用来编码一个 BMP 范围之外的字符的。
下面是一个具体示例: const str = '𠜎'; // 这是一个代理对字符 console.log(str.length); // 输出 2,因为它实际上由两个 UTF-16 编码单元组成 // 使用 codePointAt 获取完整的 Unicode 代码点 const codePoint = str.codePointAt(0); console.log(codePoint.toString(16)); // 输出 "2070e" // 如果跳过第二个代码单元,我们仍然能正确地解析整个字符串 for (let i = 0; i < str.length; i++) { const code = str.codePointAt(i); if (code > 0xFFFF) { i++; // 跳过代理对的第二个部分 } console.log(code.toString(16)); } 当然,在这种做法中有一个隐含的假设,即字符串是“良构”的,也就是说,它不包含孤立的、不完整的代理对。如果你不能保证这一点,那么额外的验证代码可能是必要的。但在大多数正常的操作环境中,代理对应该是完整和良构的。
