41

在用 JavaScript 编写加密方法时,我开始想知道我的字符串使用的是什么字符编码,以及为什么。

什么决定了 JavaScript 中的字符编码?是标准吗?通过浏览器?由 HTTP 请求的标头决定?在<META>包含它的 HTML 标记中?提供页面的服务器?

通过我的经验测试(更改不同的设置,然后使用charCodeAt一个足够奇怪的字符并查看该值与哪个编码匹配),它似乎总是 UTF-8 或 UTF-16,但我不确定为什么

经过一番疯狂的谷歌搜索后,我似乎无法为这个简单的问题找到一个确凿的答案。

4

2 回答 2

28

E262 第 8.4 节:

String 类型是零个或多个 16 位无符号整数值(“元素”)的所有有限有序序列的集合。String 类型通常用于表示正在运行的 ECMAScript 程序中的文本数据,在这种情况下,String 中的每个元素都被视为一个代码单元值(参见第 6 条)。每个元素都被视为在序列中占据一个位置。这些位置用非负整数索引。第一个元素(如果有)在位置 0,下一个元素(如果有)在位置 1,依此类推。字符串的长度是其中元素的数量(即 16 位值)。空字符串的长度为零,因此不包含任何元素。

当一个字符串包含实际的文本数据时,每个元素都被认为是一个 UTF-16 代码单元。无论这是否是字符串的实际存储格式,字符串中的字符都按其初始代码单元元素位置编号,就好像它们使用 UTF-16 表示一样。对字符串的所有操作(除非另有说明)都将它们视为未区分的 16 位无符号整数序列;他们不确保生成的字符串是规范化的形式,也不确保语言敏感的结果。

这个措辞有点狡猾。这似乎意味着所有重要的东西都将字符串视为每个字符都是 UTF-16 字符,但同时没有任何东西可以确保它都是有效的。

需要明确的是,其意图是字符串由 UTF-16 代码点组成。在ES2015中,“字符串值”的定义包括以下注释:

String 值是 String 类型的成员。序列中的每个整数值通常代表一个 16 位的 UTF-16 文本单元。但是,ECMAScript 对这些值没有任何限制或要求,只是它们必须是 16 位无符号整数。

因此,即使字符串包含不能用作正确 Unicode 字符的值,它仍然是字符串。

于 2012-06-21T15:17:47.927 回答
13

JavaScript 本身没有默认的字符编码。就规范而言,JavaScript 程序是一系列抽象字符。当通过网络传输或仅存储在计算机中时,抽象字符必须以某种方式进行编码,但其机制不受 ECMAScript 标准的控制。

ECMAScript标准的第 6 节使用 UTF-16 作为参考编码,但没有将其指定为默认编码。使用 UTF-16 作为参考在逻辑上是不必要的(参考 Unicode 数字就足够了),但它可能被认为可以帮助人们。

不应将此问题与字符串文字或一般字符串的解释相混淆。像“Φ”这样的文字需要与程序的其余部分一起进行某种编码;这可以是任何编码,但在解析编码后,文字将根据字符的 Unicode 编号解释为整数。

当通过 Internet 传输 JavaScript 程序(如“外部 JavaScript 文件”)时,适用RFC 4329,脚本媒体类型。第 4 条定义了机制:主要检查诸如 HTTP 标头之类的标头,并且charset那里的参数将被信任。(实际上,Web 服务器通常不会为 JavaScript 程序指定这样的参数。)其次,应用 BOM 检测。否则,将隐含 UTF-8。

该机制的第一部分有些模棱两可。它可能被解释为charset仅与实际 HTTP 标头中的参数相关,或者可能被扩展到元素中的charset参数。script

如果 JavaScript 程序嵌入在 HTML 中,无论是通过script元素还是某个事件属性,那么它的字符编码当然与 HTML 文档的字符编码相同。指定 HTML 4.01 规范的字符编码部分定义了解析机制,按以下顺序:charset在 HTTP 标头中,charset在 中metacharset在访问文档所遵循的链接中,最后是启发式(猜测),这可能涉及很多事情;参看。HTML5 草案中复杂的解析机制。

于 2012-06-21T16:39:17.060 回答