A Roadmap
  • Introduction
  • Roadmap
  • Basics
    • Basic Terminal Usage
      • Shell
        • 基本
        • 变量
        • 传递参数
        • 运算符
        • 命令
        • 流程控制
        • 函数
        • 输入输出重定向
    • Character Encoding
      • 字符编码
    • Data Structures & algorithms
    • Network
      • TCP/IP
      • Http/Https
        • 浏览器缓存
        • Status Code
        • GET & POST
        • HTTPS 握手过程
        • HostOnly Cookie
      • CDN
        • CDN 工作原理
    • Version Control
      • git message format
      • git commands
    • Principles
    • Design Patterns
    • Others
      • JSON
      • 正则表达式
  • Front End
    • Web Standard
      • Html
      • CSS
        • font-face 小记
        • Grid 布局简易笔记
      • Javascript
        • Ajax
          • Fetch
          • XMLHttpRequest
        • DOM
          • Selection
          • 常用 DOM 操作
          • script 标签的几个属性
        • Ecmascript
          • this 关键字
          • Event Loop
          • 隐式转换
          • Date
        • Event
          • 模拟事件
          • Others
    • Development
      • Package Management
        • npm
      • Modulization
        • 模块化机制
        • webpack 打包解析
      • Architecture
      • Build Tools
        • 如何编写一个自定义的 eslint 规则?
      • Debug
        • 移动端调试 web
      • Pre/Post Processors
      • Test
        • Jest Snapshot 使用指南
      • Type Checkers
        • TS 中 enum 的编译结果
    • Libs & frameworks
    • Platforms
      • Browser
        • Basics
          • 从输入 URL 到页面加载完成都发生了什么事情?
          • HTML 加载的过程示意图
          • 为什么读取某些属性,也会导致回流?
          • Chrome 进程模型
        • PWA
        • Compatible
        • Cross Origin
        • Performance
          • 性能检测:performance 对象
          • 性能指标
        • Others
          • 移动端 web 开发笔记
      • Server
      • Desktop Applications
      • Mobile Applications
        • Flutter 在移动端和 Web 端的技术实现
  • Back End
    • outline
    • Languages
      • Node
        • Event Loop
        • NodeJS 中的进程与线程
        • NodeJS 中的 esModule 与 commonJS
  • Clients
    • outline
    • 安装 IPA 包
  • DevOps
    • Languages
    • OS Concepts
    • Servers & terminal
  • UI & UX
    • outline
  • Others
    • Posts
      • 使用 node 爬取数据并导出到 excel
      • antd 1.x datepicker 时区问题
      • babel-transform-runtime 踩坑记录
      • lodash 按需加载注意事项
      • 记一次项目迁移的踩坑记录
      • 时区与JS中的Date对象
      • 记一次 vue + ts 开发踩坑
    • Tools
      • 个人常用的工具分享
      • tmux 简要笔记
Powered by GitBook
On this page
  • 字节与位
  • 编码类型
  • ASCII
  • unicode
  • GBK
  • UCS2
  • ES6 对unicode的支持
  • 1. 正确识别字符
  • 2. 码点表示法
  • 3. 字符串处理函数
  • 4. 正则表达式
  • 5. 多字节码点字符的长度计算
  • 参考资料

Was this helpful?

  1. Basics
  2. Character Encoding

字符编码

PreviousCharacter EncodingNextData Structures & algorithms

Last updated 6 years ago

Was this helpful?

字节与位

每一个二进制位(bit)有0和1两种状态,因此八个二进制位就可以组合出256种状态,这被称为一个字节(byte)。也就是说,一个字节一共可以用来表示256种不同的状态,每一个状态对应一个符号,就是256个符号,从00000000到11111111。

编码类型

ASCII

  • ASCII (American Standard Code for Information Interchange)

unicode

BMP

BMP(Basic Multilingual Plane)字符 Unicode 是目前绝大多数程序使用的字符编码。Unicode 标识符通过一个明确的名字和一个整数来作为它的码点/码位 (code point)。比如,“©️” 字符可以用“版权标志” 和码位 U+00A9 (0xA9,也可以写作十进制 169) 来表示。

码点/码位是为每一个字符提供一个全局唯一的标识符,一个码位映射一个字符,码位值的范围是从U+0000到U+10FFFF,可以表示超过110万个符号。

Unicode 字符分为 17 组平面,每个平面拥有 2^16 (65,536) 个码位。每一个码位都可以用 16 进制 xy0000 到 xyFFFF 来表示,这里的 xy 是表示一个 16 进制的值,从 00 到 10。

而当 xy 是 00 (码点范围是从U+0000到U+FFFF) 的时候,也就是 Unicode 最前 2^16 (65,536) 个字符,被称为基本平面 BMP(Basic Multilingual Plane),最常见的字符都在这个平面上,这也是 Unicode 最先定义和最先公布的一个平面。

其余 16 个平面(U+010000 到 U+10FFFF)称为补充平面(supplementary planes, or astral planes),也称之为补充字符,相对于 BMP 字符而言,这些字符称之为非 BMP 字符。要区分是非 BMP 字符很简单:其码位需要超过 4 位 16 进制表示

非BMP码点

要用两个字节的码点表示非BMP码点,需要用到代理对:

前两个字节称为高位代理或者顶部代理,范围在 0xD800 到 0xDBFF 之间;

后两个字节称为低位代理或者尾部代理,范围在 0xDC00 到 0xDFFF 之间

UTF-8

UTF-8 的编码规则很简单,只有二条:

1)对于单字节的符号,字节的第一位设为0,后面7位为这个符号的 Unicode 码。因此对于英语字母,UTF-8 编码和 ASCII 码是相同的。

2)对于n字节的符号(n > 1),第一个字节的前n位都设为1,第n + 1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的 Unicode 码。

GBK

  • GB2312

UCS2

  • UCS (Universal Coded Character Set)

    Javascript 使用ucs-2编码

ES6 对unicode的支持

1. 正确识别字符

ES6可以自动识别4字节的码点

2. 码点表示法

JavaScript允许直接用码点表示Unicode字符,写法是"反斜杠+u+码点"。

'好' === '\u597D' // true

// ES6支持 使用{}符号来显示 4字节码点
'𝌆' === '\u{1D306}'    // true
'𝌆' === '\u1D306'      // false

3. 字符串处理函数

ES6新增了几个专门处理4字节码点的函数。

  • String.fromCodePoint():从Unicode码点返回对应字符

  • String.prototype.codePointAt():从字符返回对应的码点

codePointAt vs charCodeAt

对于 BMP 字符,charCodeAt 和 codePointAt 的行为一致,都是返回整个字符的码位 (code point);

对于非 BMP 字符,charCodeAt 通过指定参数,返回不同位置上的 code unit 值;而 codePointAt 当参数为 0 时,返回整个字符的码位 (code point),当参数为 1 时,返回的是低位代理 code unit 的值。

反转包含多字节码点的字符串

emoji字符一般是多字节码点。因为js不能识别两个字节以上的码点,因此使用以下方式反转字符串,会错误的截取字符:

'📦123'.split('').reverse().join(''); // '321��'

这里📦的unicode编码是四字节,split方法无法正确识别,将一个四字节的字符识别为两个两字节的字符,所以出现了乱码。

可以使用Array.from方法:

Array.from('📦123').reverse().join(''); // '321📦'

4. 正则表达式

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

/^.$/.text('𝌆');   // flase
/^.$/u.text('𝌆');  // true

5. 多字节码点字符的长度计算

多字节码点在使用高低位的代理对兼容两字节码点,可以通过正则表达式匹配代理对,匹配出多字节码点字符的长度。

var regexAstralSymbols = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g; // 匹配UTF-16的代理对

function countSymbols(string) {
    return string
        // 把代理对改为一个BMP的字符.
        .replace(regexAstralSymbols, '_')
        // 这时候取长度就妥妥的啦.
        .length;
}
countSymbols('💩'); // 1

参考资料

unicode.org
字符编码笔记:ASCII,Unicode 和 UTF-8
Unicode与JavaScript详解
JavaScript Unicode 编码那些事
Javascript有个Unicode的天坑