php做网站多少钱,做百度推广需要网站吗,做网站策划师的图片,给自己的家乡建设网站上个月#xff0c;我做了一次分享#xff0c;详细介绍了Unicode字符集#xff0c;以及JavaScript语言对它的支持。下面就是这次分享的讲稿。 一、Unicode是什么#xff1f; Unicode源于一个很简单的想法#xff1a;将全世界所有的字符包含在一个集合里#xff0c;计算机只…上个月我做了一次分享详细介绍了Unicode字符集以及JavaScript语言对它的支持。下面就是这次分享的讲稿。 一、Unicode是什么 Unicode源于一个很简单的想法将全世界所有的字符包含在一个集合里计算机只要支持这一个字符集就能显示所有的字符再也不会有乱码了。 它从0开始为每个符号指定一个编号这叫做码点code point。比如码点0的符号就是null表示所有二进制位都是0。 U0000 null上式中U表示紧跟在后面的十六进制数是Unicode的码点。 目前Unicode的最新版本是7.0版一共收入了109449个符号其中的中日韩文字为74500个。可以近似认为全世界现有的符号当中三分之二以上来自东亚文字。比如中文好的码点是十六进制的597D。 U597D 好这么多符号Unicode不是一次性定义的而是分区定义。每个区可以存放65536个216字符称为一个平面plane。目前一共有17个25平面也就是说整个Unicode字符集的大小现在是221。 最前面的65536个字符位称为基本平面缩写BMP它的码点范围是从0一直到216-1写成16进制就是从U0000到UFFFF。所有最常见的字符都放在这个平面这是Unicode最先定义和公布的一个平面。 剩下的字符都放在辅助平面缩写SMP码点范围从U010000一直到U10FFFF。 二、UTF-32与UTF-8 Unicode只规定了每个字符的码点到底用什么样的字节序表示这个码点就涉及到编码方法。 最直观的编码方法是每个码点使用四个字节表示字节内容一一对应码点。这种编码方法就叫做UTF-32。比如码点0就用四个字节的0表示码点597D就在前面加两个字节的0。 U0000 0x0000 0000U597D 0x0000 597DUTF-32的优点在于转换规则简单直观查找效率高。缺点在于浪费空间同样内容的英语文本它会比ASCII编码大四倍。这个缺点很致命导致实际上没有人使用这种编码方法HTML 5标准就明文规定网页不得编码成UTF-32。 人们真正需要的是一种节省空间的编码方法这导致了UTF-8的诞生。UTF-8是一种变长的编码方法字符长度从1个字节到4个字节不等。越是常用的字符字节越短最前面的128个字符只使用1个字节表示与ASCII码完全相同。 编号范围字节0x0000 - 0x007F10x0080 - 0x07FF20x0800 - 0xFFFF30x010000 - 0x10FFFF4 由于UTF-8这种节省空间的特性导致它成为互联网上最常见的网页编码。不过它跟今天的主题关系不大我就不深入了具体的转码方法可以参考《字符编码笔记》。 三、UTF-16简介 UTF-16编码介于UTF-32与UTF-8之间同时结合了定长和变长两种编码方法的特点。 它的编码规则很简单基本平面的字符占用2个字节辅助平面的字符占用4个字节。也就是说UTF-16的编码长度要么是2个字节U0000到UFFFF要么是4个字节U010000到U10FFFF。 于是就有一个问题当我们遇到两个字节怎么看出它本身是一个字符还是需要跟其他两个字节放在一起解读 说来很巧妙我也不知道是不是故意的设计在基本平面内从UD800到UDFFF是一个空段即这些码点不对应任何字符。因此这个空段可以用来映射辅助平面的字符。 具体来说辅助平面的字符位共有220个也就是说对应这些字符至少需要20个二进制位。UTF-16将这20位拆成两半前10位映射在UD800到UDBFF空间大小210称为高位H后10位映射在UDC00到UDFFF空间大小210称为低位L。这意味着一个辅助平面的字符被拆成两个基本平面的字符表示。 所以当我们遇到两个字节发现它的码点在UD800到UDBFF之间就可以断定紧跟在后面的两个字节的码点应该在UDC00到UDFFF之间这四个字节必须放在一起解读。 四、UTF-16的转码公式 Unicode码点转成UTF-16的时候首先区分这是基本平面字符还是辅助平面字符。如果是前者直接将码点转为对应的十六进制形式长度为两字节。 U597D 0x597D如果是辅助平面字符Unicode 3.0版给出了转码公式。 H Math.floor((c-0x10000) / 0x400)0xD800L (c - 0x10000) % 0x400 0xDC00以字符为例它是一个辅助平面字符码点为U1D306将其转为UTF-16的计算过程如下。 H Math.floor((0x1D306-0x10000)/0x400)0xD800 0xD834L (0x1D306-0x10000) % 0x4000xDC00 0xDF06所以字符的UTF-16编码就是0xD834 DF06长度为四个字节。 五、JavaScript使用哪一种编码 JavaScript语言采用Unicode字符集但是只支持一种编码方法。 这种编码既不是UTF-16也不是UTF-8更不是UTF-32。上面那些编码方法JavaScript都不用。 JavaScript用的是UCS-2 六、UCS-2编码 怎么突然杀出一个UCS-2这就需要讲一点历史。 互联网还没出现的年代曾经有两个团队不约而同想搞统一字符集。一个是1989年成立的Unicode团队另一个是更早的、1988年成立的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月Brendan Eich用了10天设计了JavaScript语言10月第一个解释引擎问世次年11月Netscape正式向ECMA提交语言标准整个过程详见《JavaScript诞生记》。对比UTF-16的发布时间1996年7月就会明白Netscape公司那时没有其他选择只有UCS-2一种编码方法可用 八、JavaScript字符函数的局限 由于JavaScript只能处理UCS-2编码造成所有字符在这门语言中都是2个字节如果是4个字节的字符会当作两个双字节的字符处理。JavaScript的字符函数都受到这一点的影响无法返回正确结果。 还是以字符为例它的UTF-16编码是4个字节的0xD834 DF06。问题就来了4个字节的编码不属于UCS-2JavaScript不认识只会把它看作单独的两个字符UD834和UDF06。前面说过这两个码点是空的所以JavaScript会认为是两个空字符组成的字符串 上面代码表示JavaScript认为字符的长度是2取到的第一个字符是空字符取到的第一个字符的码点是0xDB34。这些结果都不正确 解决这个问题必须对码点做一个判断然后手动调整。下面是正确的遍历字符串的写法。 while (index length) {// ...if (charCode 0xD800 charCode 0xDBFF) {output.push(character string.charAt(index));} else {output.push(character);}
}上面代码表示遍历字符串的时候必须对码点做一个判断只要落在0xD800到0xDBFF的区间就要连同后面2个字节一起读取。 类似的问题存在于所有的JavaScript字符操作函数。 String.prototype.replace()String.prototype.substring()String.prototype.slice()... 上面的函数都只对2字节的码点有效。要正确处理4字节的码点就必须逐一部署自己的版本判断一下当前字符的码点范围。 九、ECMAScript 6 JavaScript的下一个版本ECMAScript 6简称ES6大幅增强了Unicode支持基本上解决了这个问题。 1正确识别字符 ES6可以自动识别4字节的码点。因此遍历字符串就简单多了。 for (let s of string ) {// ...
}但是为了保持兼容length属性还是原来的行为方式。为了得到字符串的正确长度可以用下面的方式。 Array.from(string).length2码点表示法 JavaScript允许直接用码点表示Unicode字符写法是斜杠u码点。 好 \u597D // true但是这种表示法对4字节的码点无效。ES6修正了这个问题只要将码点放在大括号内就能正确识别。 3字符串处理函数 ES6新增了几个专门处理4字节码点的函数。 String.fromCodePoint()从Unicode码点返回对应字符String.prototype.codePointAt()从字符返回对应的码点String.prototype.at()返回字符串给定位置的字符 4正则表达式 ES6提供了u修饰符对正则表达式添加4字节码点的支持。 5Unicode正规化 有些字符除了字母以外还有附加符号。比如汉语拼音的Ǒ字母上面的声调就是附加符号。对于许多欧洲语言来说声调符号是非常重要的。 Unicode提供了两种表示方法。一种是带附加符号的单个字符即一个码点表示一个字符比如Ǒ的码点是U01D1另一种是将附加符号单独作为一个码点与主体字符复合显示即两个码点表示一个字符比如Ǒ可以写成OU004F ˇU030C。 // 方法一
\u01D1
// Ǒ// 方法二
\u004F\u030C
// Ǒ这两种表示方法视觉和语义都完全一样理应作为等同情况处理。但是JavaScript无法辨别。 \u01D1\u004F\u030C //false ES6提供了normalize方法允许Unicode正规化即将两种方法转为同样的序列。 \u01D1.normalize() \u004F\u030C.normalize() // true关于ES6的更多介绍请看《ECMAScript 6入门》。 我的讲稿就是上面这些内容当天的PPT请看这里。转载于:https://www.cnblogs.com/ranzige/p/4186683.html