专栏首页阮一峰的网络日志Unicode与JavaScript详解

Unicode与JavaScript详解

上个月,我做了一次分享,详细介绍了Unicode字符集,以及JavaScript语言对它的支持。下面就是这次分享的讲稿。

![](/blogimg/asset/2014/bg2014121102.jpg)

## 一、Unicode是什么?

Unicode源于一个很简单的想法:将全世界所有的字符包含在一个集合里,计算机只要支持这一个字符集,就能显示所有的字符,再也不会有乱码了。

![](/blogimg/asset/2014/bg2014121103.jpg)

**它从0开始,为每个符号指定一个编号,这叫做"码点"(code point)。**比如,码点0的符号就是null(表示所有二进制位都是0)。

U+0000 = null

上式中,U+表示紧跟在后面的十六进制数是Unicode的码点。

![](/blogimg/asset/2014/bg2014121115.png)

目前,Unicode的最新版本是7.0版,一共收入了109449个符号,其中的中日韩文字为74500个。可以近似认为,全世界现有的符号当中,三分之二以上来自东亚文字。比如,中文"好"的码点是十六进制的597D。

U+597D = 好

这么多符号,Unicode不是一次性定义的,而是分区定义。每个区可以存放65536个(216)字符,称为一个平面(plane)。目前,一共有17个(25)平面,也就是说,整个Unicode字符集的大小现在是221。

最前面的65536个字符位,称为基本平面(缩写BMP),它的码点范围是从0一直到216-1,写成16进制就是从U+0000到U+FFFF。所有最常见的字符都放在这个平面,这是Unicode最先定义和公布的一个平面。

剩下的字符都放在辅助平面(缩写SMP),码点范围从U+010000一直到U+10FFFF。

![](/blogimg/asset/2014/bg2014121104.png)

## 二、UTF-32与UTF-8

Unicode只规定了每个字符的码点,到底用什么样的字节序表示这个码点,就涉及到编码方法。

**最直观的编码方法是,每个码点使用四个字节表示,字节内容一一对应码点。这种编码方法就叫做UTF-32。**比如,码点0就用四个字节的0表示,码点597D就在前面加三个字节的0。

U+0000 = 0x0000 0000 0000 0000 U+597D = 0x0000 0000 0000 597D

![](/blogimg/asset/2014/bg2014121116.png)

UTF-32的优点在于,转换规则简单直观,查找效率高。缺点在于浪费空间,同样内容的英语文本,它会比ASCII编码大四倍。这个缺点很致命,导致实际上没有人使用这种编码方法,HTML 5标准就明文规定,网页不得编码成UTF-32。

![](/blogimg/asset/2014/bg2014121105.png)

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

编号范围

字节

0x0000 - 0x007F

1

0x0080 - 0x07FF

2

0x0800 - 0xFFFF

3

0x010000 - 0x10FFFF

4

由于UTF-8这种节省空间的特性,导致它成为互联网上最常见的网页编码。不过,它跟今天的主题关系不大,我就不深入了,具体的转码方法,可以参考我多年前写的[《字符编码笔记》](http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html)。

## 三、UTF-16简介

UTF-16编码介于UTF-32与UTF-8之间,同时结合了定长和变长两种编码方法的特点。

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

![](/blogimg/asset/2014/bg2014121106.png)

于是就有一个问题,当我们遇到两个字节,怎么看出它本身是一个字符,还是需要跟其他两个字节放在一起解读?

说来很巧妙,我也不知道是不是故意的设计,在基本平面内,从U+D800到U+DFFF是一个空段,即这些码点不对应任何字符。因此,这个空段可以用来映射辅助平面的字符。

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

![](/blogimg/asset/2014/bg2014121117.png)

**所以,当我们遇到两个字节,发现它的码点在U+D800到U+DBFF之间,就可以断定,紧跟在后面的两个字节的码点,应该在U+DC00到U+DFFF之间,这四个字节必须放在一起解读。**

## 四、UTF-16的转码公式

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

U+597D = 0x597D

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

H = Math.floor((c-0x10000) / 0x400)+0xD800 L = (c - 0x10000) % 0x400 + 0xDC00

![](/blogimg/asset/2014/bg2014121107.png)

以字符

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Unicode与JavaScript详解

    上个月,我做了一次分享,详细介绍了Unicode字符集,以及JavaScript语言对它的支持。下面就是这次分享的讲稿。 ? 一、Unicode是什么? Uni...

    ruanyf
  • CSS 框架 Bulma 教程

    网页样式需要大量时间开发,最省事的方法就是使用 CSS 框架。 Bootstrap 是最著名的 CSS 框架,但是今天我想推荐另一个更轻量化、更易用的框架---...

    ruanyf
  • H5 手机 App 开发入门:技术篇

    如果你熟悉 Java 语言,可以学习安卓开发;如果熟悉脚本语言(比如 Python 或 Ruby),可以学习 Swift 语言,进行 iOS 开发;如果像我一样...

    ruanyf
  • Unicode与JavaScript详解

    上个月,我做了一次分享,详细介绍了Unicode字符集,以及JavaScript语言对它的支持。下面就是这次分享的讲稿。 ? 一、Unicode是什么? Uni...

    ruanyf
  • JavaScript 有个 Unicode 的天坑

    最近笔者在项目中遇到了emoji表情的处理,期间发现js处理多字节字符时会有较多坑,记录一下与各位分享。

    疯狂的技术宅
  • 今日推荐fucking-algorithm

    最近应该也是跳槽季,很多公司都大换血了,也有很多同行开始展望新的机会,在这个情况下,当然少不了刷题临时抱佛脚了。

    仇诺伊
  • 清官谈mysql中utf8和utf8mb4区别,请使用utf8mb4

    MySQL在5.5.3之后增加了这个utf8mb4的编码,mb4就是most bytes 4的意思,专门用来兼容四字节的unicode。好在utf8mb4...

    用户7657330
  • 这难道是UTF-8字符编码的设计缺陷?

    UTF-8都知道是啥,所有人都在用它来存储和传输文本。鄙人闲来无事研究了一下utf8的规格,发现它并没有想象中的那样完美。

    Jean
  • 机器学习性能评价指标汇总

    AUC 是 ROC (Receiver Operating Characteristic) 曲线以下的面积, 介于0.1和1之间。Auc作为数值可以直观的评价分...

    莫斯
  • Android Studio 学习笔记

    最近从Eclipse转到Android Studio IDE,很多东西需要学习,本文是个记录。

    zhangyunfeiVir

扫码关注云+社区

领取腾讯云代金券