[Effective JavaScript 笔记] 第7条:视字符串为16位的代码单元序列
Unicode编码,基础:它为世界上所有的文字系统的每个字符单位分配一个唯一的整数,该整数介于0~1114111之间,在Unicode术语中称为代码点(code point)。
和其它字符编码几乎没有任何不同(例如ASCII)。
不同在于ASCII将每个索引映射为唯一的二进制表示,但Unicode允许多个不同二进制编码的代码点。
不同的编码在要求存储的字符串数量和操作速度之间进行权衡。
目前最流行的Unicode编码方式有:UTF-8,UTF-16,UTF-32。
Unicode根据历史的数据,错误的估算了代码点的容易范围。
最初,认为只需要216代码点,所以产生了UCS-2,其为16位编码的原始标准。一个代码点可以容纳16位的数字,简单的方法是将代码点与其编码元素一对一地映射起来,这称为一个代码单元(code unit)。
UCS-2是由独立的16位的代码单元组成,每个代码单元对应一个单独的Unicode代码点。这种编码方法的主要好处在于索引字符串是一种代码小的,固定时间的操作。获取某个字符串的第n个代码点只是简单简单地选取数组的第n个16位元素。
下面示例:

这个字符串,里面的每个字符由最初的16位范围中的代码点组成。对于Unicode字符串,代码点和编码元素能完全匹配。
JS字符串采用这16位编码每一个元素。如果还保持20世纪90年代初的做法,JS字符串的每个元素还是对应一个单独的代码点。
Unicode从216扩展到了220个代码点。新增加后的范围被组织为17个大小为216代码点的子范围。
第一个子范围,称为基本多文种平面,包含最初的216个代码点。余下的16个范围称为辅助平面。
一旦代码点的范围扩展了,UCS-2就变得过时了。它需要通过扩展来表示这些附加的代码点。基替代者UTF-16和它类似。
UTF-16采用代理对表示附加的代码点。一对16位的代码单元共同编码一个等于或大于216的代码点。(有点乱,是这样吧。一个代理对等于两个16位的代码单元。一个代码单元是代码点与其编码元素一对一地映射。)
举个例子:
高音谱号“
”的代码点为U+1D11E(代码点数119070的Unicode的惯用16进制写法)
其由UTF-16格式的代码单元0xd834和0xddle共同表示。可以通过合并这两个代码单元选择的位来对代码点进行解码。(这种编码保证了这些代理对绝不会与有效的BMP代码点混淆,甚至从字符串中间的某个位置进行搜索,也可以随时识别一个代理对。)

由于UTF-16的每个代码点编码需要一个或两个16位的代码单元,因此UTF-16是一种可变长度的编码。
- 长度为n的字符串在内存中的大小变化基于字符串特定的代码点。
- 查找字符串中的第n个代码点不再是一个固定时间的操作。
- 搜索需要从字符串的开始进行。
当Unicode扩大规模时,JS已经采用了16位的字符串元素。字符串属性和方法都是基于代码单元层级,而不是代码点层级。
所以每当字符串包含辅助平面中的代码点时,js将每个代码点表示为两个元素而不是一个(一对UTF-16代理对的代码点)
一个js字符串的元素是一个16位的代码单元。
提取字符串的某个字符得到的是代码单元,而不是代码点。
正则表达式也工作于代码单元层级。其单字符模式(“.”)匹配一个单一的代码单元。
JS内置的字符串数据类型工作于代码单元层级,但这并不能阻止一些API意识到代码点和代理对。一些标准的ECMAScript库正确地处理了代理对。
URI操作函数:sendcodeURI,decodeURI,encodeURIComponent和decodeURIComponent。
提示
- js字符串是由16位的代码单元组成,而不是由Unicode代码点组成。
- js使用两个代码单元表示216及其以上的Unicode代码点。这两个代码单元被称为代理对。
- 代理对甩开了字符串元素计数,length,charAt,charCodeAt方法及正则表达式模式受到了影响。
- 使用第三方的库编写可识别代码点的字符串操作。
- 每当使用一个含有字符串操作的库时,都需要查阅该库文档,看好像处理代码点的整个范围。
后记
这节看得我很蒙B,整不太懂,我平时的工作环境中,也没有遇到过这方面的BUG。
页面编码是utf-8或gbk的,是否可以不用考虑上面说的?
现在只是知道在内存的存储过程中,每种情况对应的存储方式。
再想进一步的,可以自己再去网上找资料看了。
进一步阅读
网上找了几个写这方面的文章,有兴趣自己去读吧。
简单几句话总结Unicode,UTF-8和UTF-16
Unicode(UTF-8, UTF-16)令人混淆的概念
- 为什么 UTF-8 编码比 UTF-16 编码应用更广泛?
UTF-8 GBK UTF8 GB2312 之间的区别和关系
[Effective JavaScript 笔记] 第7条:视字符串为16位的代码单元序列的更多相关文章
- [Effective JavaScript 笔记]第27条:使用闭包而不是字符串来封装代码
函数是一种将代码作为数据结构存储的便利方式,代码之后可以被执行.这使得富有表现力的高阶函数抽象如map和forEach成为可能.它也是js异步I/O方法的核心.与此同时,也可以将代码表示为字符串的形式 ...
- [Effective JavaScript 笔记] 第4条:原始类型优于封闭对象
js有5种原始值类型:布尔值.数字.字符串.null和undefined. 用typeof检测一下: typeof true; //"boolean" typeof 2; //&q ...
- [Effective JavaScript 笔记] 第5条:避免对混合类型使用==运算符
“1.0e0”=={valueOf:function(){return true;}} 是值是多少? 这两个完全不同的值使用==运算符是相等的.为什么呢?请看<[Effective JavaSc ...
- [Effective JavaScript 笔记]第28条:不要信赖函数对象的toString方法
js函数有一个非凡的特性,即将其源代码重现为字符串的能力. (function(x){ return x+1 }).toString();//"function (x){ return x+ ...
- [Effective JavaScript 笔记]第46条:使用数组而不要使用字典来存储有序集合
对象属性无序性 js对象是一个无序属性集合. var obj={}; obj.a=10; obj.b=30; 属性a和属性b并没有谁前谁后之说.for...in循环,先输出哪个属性都有可能.获取和设置 ...
- [Effective JavaScript 笔记]第68条:使用promise模式清洁异步逻辑
构建异步API的一种流行的替代方式是使用promise(有时也被称为deferred或future)模式.已经在本章讨论过的异步API使用回调函数作为参数. downloadAsync('file.t ...
- [Effective JavaScript 笔记]第66条:使用计数器来执行并行操作
第63条建议使用工具函数downloadAllAsync接收一个URL数组并下载所有文件,结果返回一个存储了文件内容的数组,每个URL对应一个字符串.downloadAllAsync并不只有清理嵌套回 ...
- [Effective JavaScript 笔记]第65条:不要在计算时阻塞事件队列
第61条解释了异步API怎样帮助我们防止一段程序阻塞应用程序的事件队列.使用下面代码,可以很容易使一个应用程序陷入泥潭. while(true){} 而且它并不需要一个无限循环来写一个缓慢的程序.代码 ...
- [Effective JavaScript 笔记]第20条:使用call方法自定义接收者来调用方法
不好的实践 函数或方法的接收者(即绑定到特殊关键字this的值)是由调用者的语法决定的.方法调用语法将方法被查找的对象绑定到this变量,(可参阅之前文章<理解函数调用.方法调用及构造函数调用之 ...
随机推荐
- Jsp内置对象及EL表达式的使用
一.JSP的内置对象(9个JSP内置对象) JSP的内置对象引用名称 对应的类型 request HttpServletRequest response HttpServletResponse ses ...
- 关于Chrome的开发15个小技巧
一.快速查找文件 如果你使用过Sublime,那么你会知道’Go to anything’的强大.没错,Chrome现在也有了这一功能. 操作如下: 1.F12打开你的Chrome调试器: 2.按下C ...
- setter方法的内存错误
- (void)setList:(ClassicList *)list { self.list = list; _titleLabel.text = list.activityName; _addre ...
- json_decode详解
json_decode是php5.2.0之后新增的一个PHP内置函数,其作用是对JSON 格式的字符串进行编码. json_decode的语法规则:json_decode ( string $j ...
- 软工实践个人练习-使用github进行代码管理
1.掌握使用Git进行代码版本,使用github进行代码托管. 2.创建小组Organization,并邀请组员进来. 3.将代码库https://github.com/sefzu2015/AutoC ...
- ansible 小试身手
我们安装好了ansible之后 配置了免密码登陆 现在我们可以检查一下管理主机和被管理主机的连通性 ansible all -m ping 在我们的实际生产中我们倾向于使用普通用户用sud ...
- js弹出窗口总结6种弹窗方法
注: //关闭,父窗口弹出对话框,子窗口直接关闭 this.Response.Write("<script language=javascript>window.close(); ...
- BZOJ2302 [HAOI2011]Problem c
Description 给n个人安排座位,先给每个人一个1~n的编号,设第i个人的编号为ai(不同人的编号可以相同),接着从第一个人开始,大家依次入座,第i个人来了以后尝试坐到ai,如果ai被占据了, ...
- BZOJ1208 宠物收养所
Description 最近,阿Q开了一间宠物收养所.收养所提供两种服务:收养被主人遗弃的宠物和让新的主人领养这些宠物.每个领养者都希望领养到自己满意的宠物,阿Q根据领养者的要求通过他自己发明的一个特 ...
- TYVJ1864 守卫者的挑战
P1864 [Poetize I]守卫者的挑战 时间: 1000ms / 空间: 131072KiB / Java类名: Main 描述 打开了黑魔法师Vani的大门,队员们在迷宫般的路上漫无目的地搜 ...