We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
中国有句成语, 叫见微知著. 意思是通过一点点细微的东西可以看到背后的很多东西.
在阅读代码的过程之中, 很多的知识点都需要MDN的文档来帮助理解, 那些仅仅见过几次, 但是却没有怎么理解的东西.比如前面几篇的关于Map,WeakMap, DataView的东西.就是一些基本知识的补充.
Map
WeakMap
DataView
同样, 看到了以下的代码, 感觉自己进入了未知领域.
/** * Gets the size of an ASCII `string`. * * @private * @param {string} string The string inspect. * @returns {number} Returns the string size. */ var asciiSize = baseProperty('length');
看到以上的代码, 想到了几个问题
如果还不能很有底气的回答上来, 那么证明js的一些基本的知识还没有巩固到位.
console.log("𐐷".length); // => 2
是不是有些奇怪, JavaScript的length,我们平常都用的比较多, 但是也有不灵的时候.
这是关于Unicode, 和UTF-16编码的问题. 首先说下什么是编码字符集, 字符编码表, 在现代的编码模型之中, 有5个层次, 其中, 编码字符集, 字符编码表分别是第2,3个层次的概念.
编码字符集, 规定了一个字符集里面的字符, 及其对应的坐标(也叫码位).一个字符所占用的码位称为码位值, 而字符集里面的字符, 映射到对应的坐标, 就叫编码字符集.
这里有个概念, 叫编码空间, 也就是包含了所有的字符的空间维度, 比如, Unicode的编码空间从U+0000到U+10FFFF,共有1,112,064个码位(code point)可用来映射字符.此外, 编码空间也可以用点, 行, 面的形式来描述.
而javascript用的UTF-16编码, 说的指的是编码方案, 是字符集(Unicode)的编码方案, 规定了采用16bit来储存1,112,064个码位.
问题是16位只能对应65536个码位, 怎么储存超过65536部分的字符呢? 这就是字符编码表的作用了.
字符编码表,(CEF:Character Encoding Form) 字符编码表, 就是通过规定一个码元一对一隐射到编码字符集, 一个最简单的字符编码表, 就是使用足够多的容量, 可以实现最简单的一对一映射. 但是, 这只是在对非CJK字符编码的时候, 有效,CJK文字每个文字都占据一个码位, 需要的码位远远超过一个固定的数, 而且需要考虑到文字拓展的问题, 不断有新的文字产生, 需要占据码位.
比如一个16bit的编码方案, 一对一映射的形式, 只能编码65536个码位. 所以需要实现Unicode编码的话, 就需要另辟蹊径了.
CJK字符编码, 中日韩系列的字符, 由单个字母组成一个单词, 编码字符集只需要储存单个字母, 而不需要储存单词,可以节省大量的码位.
所以, UTF-16面对Unicode怎么去编码的, 怎么去用16bit的数量, 把1,112,064个码位值隐射到16bit上面的?
Unicode 有1,112,064个码位, 从U+0000到U+10FFFF, 可以分为BMP, 和非BMP
BMP, 第一个平面称为基本多语言平面(Basic Multilingual Plane, BMP), 其他平面称为辅助平面(Supplementary Planes)
总的来说, 就是前面0-65536 个字符, 是常用的字符, 可以涵盖我们普通的时候, 比如我们中文里面的都是包括在BMP里面的, 而不包括的字符, 就如𐐷.
𐐷
BMP: U+000000 - U+00FFFF, 基本平面, 在基本平面里面, 有一个范围规定是不映射码位的, 而用对编码方案的支持, 这个范围是U+D800 - U+DFFF, 共8 * 16 * 16=2048个字符
BMP: U+000000 - U+00FFFF
U+D800 - U+DFFF
非BMP: U+010000 - U+10FFFF, 辅助平面
非BMP: U+010000 - U+10FFFF
在面对一些非BMP的字符的时候, UTF-16对非BMP是使用32bit来表示的. 就是说, 𐐷 在UTF-16下是用2个16bit来表示. 这个也是为什么在打印𐐷.length===2的原因.
也是lodash之中函数定义去获取长度的属性, 叫asciiSize的原因,因为UTF-16, 在JavaScript中, ascii字符也是16bit/length.
asciiSize
上面说道UTF-16在表示非BMP字符的时候, 是用2个16bit, 也就是用2个字符长度32bit, 去表示Unicode里面的一个非BMP字符. 32bit 称作代理对, 区分前导代理, 后尾代理.
规则是这样的:
U+3FF
然后, JavaScript在检查字符的时候, 去按照16bit一个单位去寻找, 发现这个地址在U+D800 - U+DFFF内, 那么就可以确定, 他是32bit的非BMP字符, 会再去取下一个16bit的字符, 还原码位, 再合并, 去Unicode里面寻找字符值.
参考链接: https://zh.wikipedia.org/wiki/UTF-16#UTF-16%E7%9A%84%E7%B7%A8%E7%A2%BC%E6%A8%A1%E5%BC%8F https://zh.wikipedia.org/wiki/%E5%AD%97%E7%AC%A6%E7%BC%96%E7%A0%81 注: 本文的github地址为:lodash源码解读(10)-String.prototype.length 一定等于1吗 如有版权问题,或其他问题, 请给作者留言,感谢!
The text was updated successfully, but these errors were encountered:
utf-16 BMP 基本面用来做映射的只有2048个数, 也就是当码位值超过24位, 这时减去BMP的16位的时候, 得出的码位值大于20位, 那么就不能分拆成2位10位的数组. 所以当前 UTF-16支持的码位是 65536+16*65536 = 1114112个字符. 当Unicode的字符集超出这个范围的时候, 就不能用UTF-16了.可能只能用UTF-32.
65536+16*65536
Sorry, something went wrong.
No branches or pull requests
前言
中国有句成语, 叫见微知著. 意思是通过一点点细微的东西可以看到背后的很多东西.
在阅读代码的过程之中, 很多的知识点都需要MDN的文档来帮助理解, 那些仅仅见过几次, 但是却没有怎么理解的东西.比如前面几篇的关于
Map
,WeakMap
,DataView
的东西.就是一些基本知识的补充.同样, 看到了以下的代码, 感觉自己进入了未知领域.
String的一些理解
看到以上的代码, 想到了几个问题
如果还不能很有底气的回答上来, 那么证明js的一些基本的知识还没有巩固到位.
编码字符集, 字符编码表
是不是有些奇怪, JavaScript的length,我们平常都用的比较多, 但是也有不灵的时候.
这是关于Unicode, 和UTF-16编码的问题.
首先说下什么是编码字符集, 字符编码表, 在现代的编码模型之中, 有5个层次, 其中, 编码字符集, 字符编码表分别是第2,3个层次的概念.
编码字符集, 规定了一个字符集里面的字符, 及其对应的坐标(也叫码位).一个字符所占用的码位称为码位值,
而字符集里面的字符, 映射到对应的坐标, 就叫编码字符集.
这里有个概念, 叫编码空间, 也就是包含了所有的字符的空间维度, 比如, Unicode的编码空间从U+0000到U+10FFFF,共有1,112,064个码位(code point)可用来映射字符.此外, 编码空间也可以用点, 行, 面的形式来描述.
而javascript用的UTF-16编码, 说的指的是编码方案, 是字符集(Unicode)的编码方案, 规定了采用16bit来储存1,112,064个码位.
问题是16位只能对应65536个码位, 怎么储存超过65536部分的字符呢?
这就是字符编码表的作用了.
字符编码表,(CEF:Character Encoding Form)
字符编码表, 就是通过规定一个码元一对一隐射到编码字符集, 一个最简单的字符编码表, 就是使用足够多的容量, 可以实现最简单的一对一映射. 但是, 这只是在对非CJK字符编码的时候, 有效,CJK文字每个文字都占据一个码位, 需要的码位远远超过一个固定的数, 而且需要考虑到文字拓展的问题, 不断有新的文字产生, 需要占据码位.
比如一个16bit的编码方案, 一对一映射的形式, 只能编码65536个码位. 所以需要实现Unicode编码的话, 就需要另辟蹊径了.
UTF-16
所以, UTF-16面对Unicode怎么去编码的,
怎么去用16bit的数量, 把1,112,064个码位值隐射到16bit上面的?
Unicode
Unicode 有1,112,064个码位, 从U+0000到U+10FFFF, 可以分为BMP, 和非BMP
总的来说, 就是前面0-65536 个字符, 是常用的字符, 可以涵盖我们普通的时候, 比如我们中文里面的都是包括在BMP里面的, 而不包括的字符, 就如
𐐷
.BMP: U+000000 - U+00FFFF
, 基本平面, 在基本平面里面, 有一个范围规定是不映射码位的, 而用对编码方案的支持, 这个范围是U+D800 - U+DFFF
, 共8 * 16 * 16=2048个字符非BMP: U+010000 - U+10FFFF
, 辅助平面在面对一些非BMP的字符的时候, UTF-16对非BMP是使用32bit来表示的. 就是说,
𐐷
在UTF-16下是用2个16bit来表示. 这个也是为什么在打印𐐷
.length===2的原因.也是lodash之中函数定义去获取长度的属性, 叫
asciiSize
的原因,因为UTF-16, 在JavaScript中, ascii字符也是16bit/length.非BMP字符的UTF-16映射规则
上面说道UTF-16在表示非BMP字符的时候, 是用2个16bit, 也就是用2个字符长度32bit, 去表示Unicode里面的一个非BMP字符. 32bit 称作代理对, 区分前导代理, 后尾代理.
规则是这样的:
U+3FF
, 这也是只需要2048个位置就能够隐射所有非BMP字符的原因.然后, JavaScript在检查字符的时候, 去按照16bit一个单位去寻找, 发现这个地址在
U+D800 - U+DFFF
内, 那么就可以确定, 他是32bit的非BMP字符, 会再去取下一个16bit的字符, 还原码位, 再合并, 去Unicode里面寻找字符值.小结
The text was updated successfully, but these errors were encountered: