手机版

论Unicode和JavaScript的发展历史

时间:2021-10-14 来源:互联网 编辑:宝哥软件园 浏览:

1.什么是Unicode?

Unicode来源于一个非常简单的思想:世界上所有的字符都包含在一个集合中,只要计算机支持这个字符集,所有的字符都可以显示,不会出现乱码字符。

它从0开始,给每个符号分配一个数字,称为“代码点”。例如,代码点0的符号为空(这意味着所有二进制位都为0)。

复制代码如下:U 0000=空。

在上式中,u表示紧跟其后的十六进制数是Unicode的码位。

目前,Unicode的最新版本是7.0版本,共有109,449个符号,包括74,500个中、日、韩文字符。大致可以认为,世界上现存的符号有三分之二以上来自东亚文字。比如中文‘好’的码点是十六进制的597D。

复制代码如下:U 597D=OK。

这么多符号,Unicode不是一次定义,而是分区定义的。每个区域可以存储65,536 (216)个字符,称为平面。目前有17 (25)个平面,这意味着现在整个Unicode字符集的大小是221。

前65536位称为基本平面(缩写为BMP),其码点范围为0到216-1,用十六进制写时为U 0000到U FFFF。所有最常见的字符都放在这个平面上,这是Unicode定义和发布的第一个平面。

其余字符放在辅助平面上(缩写为SMP),码点范围从U 010000到U 10FFFF。

第二,UTF-32和UTF-8。

Unicode只指定每个字符的代码点,编码方式涉及用什么样的字节顺序来表示这个代码点。

最直观的编码方式是每个码点用四个字节表示,字节的内容与码点一一对应。这种编码方法称为UTF-32。例如,代码点0由四个字节的0表示,代码点597D之前是两个字节的0。

复制代码如下: u 0000=0x 0000 0000 u 597d=0x 0000 597d。

UTF-32转换规则简单直观,搜索效率高。缺点是浪费空间。对于内容相同的英文文本,它将比ASCII编码大四倍。这个缺点是致命的,这导致实际上没有人使用这种编码方法。HTML5标准明确规定网页不应该编码成UTF-32。

人们真正需要的是一种节省空间的编码方法,这导致了UTF-8的诞生。UTF-8是一种可变长度编码方法,字符长度范围从1字节到4字节。常用字符越多,字节越短。前128个字符仅用一个字节表示,与ASCII码完全相同。

序列号范围字节0x 0000-0x 007 f10x 0080-0x 07 ff20x 0800-0x fffff 30 x 010000-0x 10 fff 4。

由于节省空间的特点,UTF-8已经成为互联网上最常见的网页编码。不过和今天的话题关系不大,就不赘述了。具体的转码方式请参考我多年前写的《字符编码笔记》。

三.UTF-16简介。

UTF-16编码介于UTF-32和UTF-8之间,结合了固定和可变长度编码方法的特点。

它的编码规则很简单:基本平面字符占用2字节,辅助平面字符占用4字节。也就是说,UTF-16的编码长度要么是2字节(U 0000到U FFFF),要么是4字节(U 010000到U 10FFFF)。

那么就有一个问题,当我们遇到两个字节的时候,怎么知道是字符本身,还是需要和另外两个字节一起解读?

很聪明,但不知道是不是刻意设计的。在基本平面上,从U D800到U DFFF是一个空段,也就是说这些码点不对应任何字符。因此,这个空段可以用来映射辅助平面的字符。

具体来说,辅助平面中有220个字符,也就是说,至少需要20个二进制位来对应这些字符。UTF-16将这20位分成两半。前10位从U D800映射到U DBFF(空间大小210),称为高位(H),后10位从U DC00映射到UDBFF(空间大小210),称为低位(L)。这意味着辅助平面字符被分成两个基本平面字符表示。

因此,当我们遇到两个字节,发现它们的码点在U D800和U DBFF之间时,就可以断定接下来两个字节的码点应该在U DC00和U DFFF之间,这四个字节必须一起解释。

4.UTF-16的转码公式。

Unicode码点转换为UTF-16时,首先要区分是基本平面字符还是辅助平面字符。如果是前者,则直接将代码点转换为对应的十六进制形式,长度为两个字节。

复制代码是:U 597D=0x597D。

如果是辅助平面字符,Unicode版给出了转码公式。

复制代码如下:h=math . floor((c-0x 10000)/0x 400)0x d 800 l=(c-0x 10000)%0x 4000x DC 00。

人物

例如,它是一个辅助平面字符,代码点为U 1D306。将其转换为UTF-16的计算过程如下。

复制代码如下:h=math . floor((0x1d 306-0x 10000)/0x 400)0x d 800=0x d 834 l=(0x1d 306-0x 10000)%0x 4000x DC 00=0x df 06。

所以,人物

的UTF-16编码为0xD834 DF06,长度为四个字节。

5.JavaScript使用哪种编码?

JavaScript语言采用Unicode字符集,但只支持一种编码方式。

这种编码既不是UTF-16、UTF-8,也不是UTF-32。上述编码方法都没有在JavaScript中使用。

JavaScript用的是UCS-2!

不及物动词UCS-2编码

如何弹出一个UCS-2?这需要一点历史。

在互联网出现之前,有两个团队想要统一角色设定。一个是1988年成立的Unicode团队,一个是1989年成立的UCS团队。当他们发现对方的存在后,很快达成一致,世界上不需要两套统一的字符集。

1991年10月,两队决定合并角色设定。也就是说,从现在开始,只会发布一套字符集,那就是Unicode,如果对之前发布的字符集进行修改,那么UCS的代码点将与Unicode完全一致。

UCS的开发进度比Unicode快。1990年,第一个编码方法UCS-2发布,它使用2个字节用代码点表示字符。当时只有一个平面,是基本平面,所以2字节就够了。UTF-16编码最晚于1996年7月发布,并明确声明为UCS-2的超集,即基本平面字符遵循UCS-2编码,辅助平面字符定义4字节的表示方法。

两者的关系很简单,就是UTF-16取代UCS-2,或者UCS-2集成到UTF-16中。所以只有UTF-16,没有UCS-2。

七、JavaScript的诞生背景。

那么,为什么JavaScript没有选择UTF-16,而是使用了已经淘汰的UCS-2呢?

答案很简单:要么不想,要么不能。因为JavaScript语言出现的时候还没有UTF-16编码。

1995年5月,BrendanEich花了10天时间设计JavaScript语言。10月,第一个解释引擎问世。次年11月,网景正式向ECMA提交了语言标准(整个过程详见《JavaScript诞生记》)。对比UTF-16的发布时间(1996年7月),可以看出当时网景公司没有其他选择,只有UCS-2是一种可用的编码方式!

八、JavaScript字符函数的局限性。

因为JavaScript只能处理UCS-2编码,所以这种语言的所有字符都是2字节。如果它们是4字节,它们将被视为两个双字节字符。JavaScript的字符函数都受此影响,无法返回正确的结果。

或者用字符

例如,它的UTF-16编码是0xD834DF06,有4个字节。问题是4字节代码不属于UCS-2,JavaScript不识别,只把它当成两个独立的字符,U D834和U DF06。如前所述,这两个代码点是空的,所以JavaScript会认为

是由两个空字符组成的字符串!

上面的代码表明JavaScript考虑了字符

的长度为2,检索到的第一个字符为空字符,检索到的第一个字符的代码点为0xDB34。这些结果都不正确!

要解决这个问题,我们必须对代码点做出判断,然后手动调整。以下是遍历字符串的正确方法。

复制代码如下: while(索引长度){//.if(char code=0x d 800 char code=0x dbff){ output。push(字符串。charat(index));} else { output.push(字符);}}

上述代码表明,在遍历字符串时,必须对代码点进行判断。只要它在0xD800至0xDBFF范围内,就必须与接下来的2个字节一起读取。

类似的问题存在于所有的JavaScript字符操作函数中。

String.prototype.replace()

String.prototype.substring()

String.prototype.slice()

.

上述函数只对2字节代码点有效。要正确处理4字节码点,必须逐个部署自己的版本,判断当前字符的码点范围。

九.ECMAScript 6。

ECMAScript 6(简称ES6)是JavaScript的下一个版本,它大大增强了对Unicode的支持,基本上解决了这个问题。

(1)正确识别字符。

ES6可以自动识别4字节码点。因此,遍历字符串要简单得多。

复制代码如下:for(字符串的字母){//.}

但是,为了保持兼容性,长度属性仍然是原始行为。要获得正确的字符串长度,可以使用以下方法。

复制代码如下:array.from(字符串)长度。

(2)码点表示。

JavaScript允许Unicode字符直接用代码点表示,编写方法是‘反斜杠U代码点’。

复制代码如下: ' OK '===' \ u597D '/true。

但是,这种表示法对于4字节代码点无效。ES6纠正了这个问题,通过将代码点放在花括号中可以正确识别它们。

(3)字符串处理功能。

ES6增加了几个专门处理4字节代码点的功能。

String.fromCodePoint():从Unicode代码点返回相应的字符。

String.prototype.codePointAt():从字符中返回相应的代码点。

String.prototype.at():返回字符串中给定位置的字符。

(4)正则表达式。

ES6提供了u修饰符,支持在正则表达式中添加4字节代码点。

(5)Unicode规范化。

有些字符除了字母之外还有其他符号。例如,在汉语拼音中,字母上方的声调是一个附加符号。声调符号对许多欧洲语言非常重要。

Unicode提供了两种表示形式。一个是带有附加符号的单个字符,即一个码点代表一个字符,例如码点为u01d1另一种是单独使用附加符号作为码点,与主字符结合显示,即两个码点代表一个字符,例如可以写成O(U 004F) ˇ(U 030C)。

复制的代码如下://方法1 ' \ u01d 1 '//'//方法2' \ u004f \ u030c'//'。

这两种表示在视觉和语义上完全相同,应该被视为等价的情况。不过,JavaScript说不准。

复制的代码如下: ' \ u01d 1 '===' \ u004f \ u030c '/false。

ES6提供了normalize方法,允许Unicode规范化’,即两种方法转换成相同的序列。

复制的代码如下:' \ u01d1 '。normalize ()===' \ u004f \ u030c '。normalize ()//true。

有关ES6的更多信息,请参见《ECMAScript 6入门》。

版权声明:论Unicode和JavaScript的发展历史是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。