什么是JavaScript中的字符串?

788 阅读4分钟

JavaScript中的字符串究竟是什么?

1.通过可见字符建模

对JavaScript字符串进行心理建模的最简单的方法,但并不完全准确,就是通过字母、数字和标点符号等字符的序列。

下面的代码样本中的字符串由5个字母和一个感叹号组成。

const message = 'Hello!';  

把字符串看成是一个可见字符的序列,也表明'Hello!' 字符串中的字符数等于6。

const message = 'Hello!';  message.length; // => 6 

如果字符来自基本的拉丁字符块,也就是127个ASCII字符,那么用可见字符(字形)来模拟字符串的方法就很有效。

但是,一旦你处理更复杂的字符,例如表情符号(😀,😁,😈),用可见字符对字符串进行建模就不准确了。

考虑一下下面这个字符串。

 const smile = '😀';

你可以看到,这个字符串只包含一个字符:咧嘴笑的脸。

但是如果你使用smile.length 属性来确定字符的数量,你可能会惊讶地发现它包含2个单位。

const smile = '😀';
smile.length; // => 2

怎么会这样:你看到的是一个字符,而length 表示有2个?

这是因为JavaScript认为字符串是一个代码单元的序列,而不是一个可见的字符序列。

让我们更详细地看看JavaScript中的字符串是什么。

2.通过代码单元建模

规范中说到了JavaScript中的字符串是什么。

字符串类型是由0个或多个16位无符号整数值("元素")组成的所有有序序列的集合。在运行的ECMAScript程序中,String类型通常用来表示文本数据,在这种情况下,String中的每个元素都被当作UTF-16代码单元值

简单地说,JavaScript中的字符串是一串数字,正是UTF-16代码单位值。

一个代码单位只是一个数字,从0x00000xFFFF 。神奇的事情发生了,因为在代码单元值和特定的字符之间存在着一种映射关系。

例如,代码单位0x0048 ,通过unicode转义序列 \u0048 ,被呈现为实际字符H

const letter = '\u0048';
letter === 'H' // => true

现在让我们直接使用UTF-16代码单元来创建'Hello!' 字符串。

const message = '\u0048\u0065\u006C\u006C\u006F\u0021';
message === 'Hello!'; // => true
message.length;       // => 6

\u0048\u0065\u006C\u006C\u006F\u0021 这就是JavaScript如何看待字符串的:作为一个代码单元的序列。请注意,所呈现的序列有6个代码单元,这与'Hello!' 字符串中的可见字符数相对应。

在UTF-16中,一个来自基本多语言平面的Unicode字符被编码为一个代码单元。

然而,来自非基本多语言平面的字符:

需要一对不可分割的代码单元(名为代理对)来进行UTF-16编码。

例如,笑脸字符'😀' ,它的编码单位是0x1F600 (数字0x1F6000xFFFF 大,因此不适合在16位中使用),用2个编码单位的序列0xD83D0xDE00

const smile = '\uD83D\uDE00';
smile === '😀'; // => true
smile.length;  // => 2

序列\uD83D\uDE00 是一个特殊的对子,名为代理对子

smile.length 评估为 ,这表示字符串基元的 属性决定了2 length 代码单元的数目。

字符串迭代器知道代用对。当你调用字符串迭代器时,例如使用传播操作符... ,它将一个代理对计算为一个长度单位。

const message = 'Hello!';
const smile = '😀';
[...message].length; // => 6
[...smile].length;   // => 1

3.总结

思考JavaScript字符串的最简单的方法是一个可见字符的序列。这种方法对英文字母、数字、ASCII字符都很有效。

然而,严格地说,JavaScript中的字符串是UTF-16代码单元的序列。string.length 属性决定了代码单元的数量,而不是可见字符的数量。