写出一个码位:HTML / CSS / JS 三套转义
字符的编码 那页讲清了「码位 (code point)」是什么 ——
那知道了码位(比如 😀 是 U+1F600),怎么在源码里把它写出来?HTML、CSS、JS 各有一套转义语法:
😀、\1F600、\u{1F600}。
三套长得像、规则各不同,各有一个易错点:CSS 的转义会贪心吞掉后面的 hex 字符,
HTML 的数字引用不认代理对,JS 的 \uXXXX 工作在码元层、能造出「半个字符」。
同一个(串)码位,各处源码里的写法
| 在哪写 | 写法 | 说明 |
|---|
三条路真的各走一遍 → 渲染出同一个字符
易错点一 · CSS:转义在哪结束?——「终结空格」
CSS 的转义是 \ + 1~6 位 hex,没有花括号包边界 —— 解析器会贪心吃 hex 字符,
直到凑满 6 位或撞上非 hex 字符。想在转义后紧跟 A/0~9/a~f 这类字符?
要么加一个终结空格(会被吞掉、不显示),要么把转义补零写满 6 位:
\20。
另外 CSS 转义不只用在字符串里 —— 标识符也靠它:id 以数字开头时选择器得写
#\31 st(1 是 U+0031),JS 里有现成的 CSS.escape('1st') 帮你算。
还有一处「直接写码位」的 CSS 语法是 unicode-range: U+4E00-9FFF,
见 font-features 的 unicode-range 页。
易错点二 · HTML:数字引用只认码位,不认代理对
HTML 的字符引用永远工作在码位层:十进制 😀、十六进制 😀,
再大的码位直接写。反过来,把 UTF-16 代理对(字符的编码那页的
D83D + DE00)拆成两个引用拼不出 😀 —— 代理区 U+D800~DFFF
不是合法字符,每个都被替换成 U+FFFD (�):
😀
��
易错点三 · JS:\uXXXX 在码元层,能造出「半个字符」
JS 字符串按 UTF-16 码元存,\uXXXX(恰 4 位)写的就是一个码元 ——
所以单写一个高位代理 '\uD83D' 完全合法,得到一个 lone surrogate:
长度 1、渲染成 �、传给只收合法 UTF-8 的 API(fetch body、TextEncoder)会被换成
U+FFFD。ES6 的 \u{…} 才工作在码位层。点下面的写法逐个看:
str.isWellFormed() 查字符串里有没有 lone surrogate,
str.toWellFormed() 把它们替换成 U+FFFD(ES2024,现代浏览器均已支持)。
「为什么 astral 字符要拆成两个码元、怎么算」见本系列 字符的编码。
速查:一个码位的全部写法
| 写法 | 用在哪 | 位数 | astral (>U+FFFF) |
|---|---|---|---|
😀 / 😀 | HTML 文本、属性值 | hex / 十进制,任意位 | ✓ 直接写码位 |
— 等命名实体 | HTML 文本(仅限有名字的字符) | — | 仅已命名字符 |
\1F600(+ 终结空格) | CSS 字符串、标识符 | hex 1~6 位 | ✓ |
\u{1F600} | JS 字符串 / 模板 / 正则(需 u/v) | hex 1~6 位 | ✓ |
\uD83D\uDE00 | JS、JSON(它只有这一种) | hex 恰 4 位 = 1 码元 | 要手拆代理对 |
\xE9 | JS | hex 恰 2 位 | ✗ 仅 U+0000~00FF |
String.fromCodePoint(0x1F600) | JS 运行时(读取端是 codePointAt / for...of) | — | ✓ |
slice 切半也会造出它)、
isWellFormed / toWellFormed、按码位遍历。「用户眼里的一个字符」还要再往上一层
(字素簇),见本系列 字素簇。
🔗 相关链接
-
WHATWG HTML · Named character references · html.spec.whatwg.org
命名实体(
—那一套)的权威清单:规范逐条列出全部 2200+ 个 named character reference 及其对应码位,并带一张「为什么有的实体可省略结尾分号、有的不行」的对照。本页表格里「命名实体」一行的出处。 - Chromium · html_entity_names.csv · source.chromium.org 浏览器引擎里这张表长什么样:Blink 的 HTML parser 直接读这份 CSV(实体名 → 码点),编译进 entity-matching 状态机。和上面 WHATWG 规范逐条对得上 —— 规范是「该有哪些」,这份 CSV 是「Chromium 真在用的那份」。