HTML 字符引用完全指南

引言

字符引用(Character References)是 HTML 和 XML 中用于表示无法直接输入或具有特殊含义的字符的转义序列。通过字符引用,开发者可以确保文档中的字符得到正确解析并且不会被误解为 HTML 标记。字符引用对于保证跨浏览器兼容性和避免编码问题至关重要。

本文将详细介绍字符引用的类型、语法以及常见应用,并列出前端开发中经常使用的字符引用。

什么是字符引用?

字符引用(Character Reference) 是 HTML 和 XML 标记语言中的一种转义机制,用于通过 ASCII 字符序列来表示那些无法直接输入、具有特殊语法含义或当前编码不支持的字符。

它的本质是一个替换规则:当解析器遇到特定的字符序列时,将其替换为对应的 Unicode 字符。

字符引用的分类

HTML 规范明确定义了两种字符引用类型:

命名字符引用(Named Character Reference)

使用预定义的英文名称来引用字符。

html 复制代码
&amp; <!-- & 符号 -->
&lt; <!-- < 小于号 -->
&gt; <!-- > 大于号 -->
&quot; <!-- " 双引号 -->
' <!-- ' 单引号 -->
&nbsp; <!-- 不间断空格 -->
&copy; <!-- © 版权符号 -->

语法规则:

  • & 开头
  • 后跟预定义的实体名称(区分大小写)
  • ; 结尾(在 HTML5 中,某些情况下可省略,但强烈建议保留)

数字字符引用(Numeric Character Reference)

数字字符引用根据进制表示方式,分为以下两类:

十进制数字字符引用(Decimal Numeric Character Reference)

使用十进制数字表示 Unicode 码点值。

语法结构

txt 复制代码
&# + 十进制数字 + ;

示例

html 复制代码
&#38;       <!-- & 符号,Unicode U+0026 -->
&#60;       <!-- < 小于号,Unicode U+003C -->
&#160;      <!-- 不间断空格,Unicode U+00A0 -->
&#169;      <!-- © 版权符号,Unicode U+00A9 -->
&#8364;     <!-- € 欧元符号,Unicode U+20AC -->
十六进制数字字符引用(Hexadecimal Numeric Character Reference)

使用十六进制数字表示 Unicode 码点值,以 xX 前缀标识进制。

语法结构

txt 复制代码
&#x + 十六进制数字 + ;    (小写 x)
&#X + 十六进制数字 + ;    (大写 X,同样有效)

示例

html 复制代码
&#x26;      <!-- & 符号,十六进制 0x26 -->
&#x3C;      <!-- < 小于号,十六进制 0x3C -->
&#xA0;      <!-- 不间断空格,十六进制 0xA0 -->
&#xA9;      <!-- © 版权符号,十六进制 0xA9 -->
&#x20AC;    <!-- € 欧元符号,十六进制 0x20AC -->
&#x1F600;   <!-- 😀 Emoji,十六进制 0x1F600 -->

分类对比表

特性 命名字符引用 数字字符引用
可读性 高(&copy; 直观) 低(&#169; 不直观)
覆盖范围 仅预定义列表 所有 Unicode 字符
记忆难度 需要记忆名称 需要查询码点
HTML5 支持 完整 完整

字符与 Unicode 码点的双向转换

JavaScript 提供了几个内置方法来实现字符与 Unicode 码点之间的双向转换。

字符 → Unicode 码点

方法1:charCodeAt()

适用于基本多文种平面(BMP)的字符,即绝大部分常用字符。

js 复制代码
// 基本用法
const char = 'A';
const codePoint = char.charCodeAt(0);
const hex = codePoint.toString(16);

console.log(`字符 "${char}" 的码点:`);
console.log(`十进制:${codePoint}`);
console.log(`十六进制:${codePoint.toString(16).toUpperCase()}`);
console.log(`HTML实体:&#${codePoint};`);
js 复制代码
// 封装为函数
function getUnicodeInfo(char) {
  const dec = char.charCodeAt(0);
  const hex = dec.toString(16).toUpperCase().padStart(4, '0');
  return {
    char: char,
    decimal: dec,
    hexadecimal: hex,
    htmlEntity: `&#${dec};`,
    unicodeNotation: `U+${hex}`
  };
}

console.log(getUnicodeInfo('<'));
console.log(getUnicodeInfo('©'));
方法2:codePointAt()

ES6 引入的方法,正确支持所有 Unicode 字符(包括 Emoji 和罕见汉字)。

js 复制代码
// 正确处理 Emoji
const emoji = '😀';
const codePoint = emoji.codePointAt(0);
const hex = codePoint.toString(16).toUpperCase();

console.log(`Emoji "${emoji}" 的码点:`);
console.log(`十进制:${codePoint}`);
console.log(`十六进制:U+${hex}`);
console.log(`HTML实体:&#${codePoint};`);
js 复制代码
// 通用封装函数(支持任意字符)
function getCodePoint(char) {
  const code = char.codePointAt(0);
  const hexRaw = code.toString(16).toUpperCase();
  // 规则:少于 4 位补到 4 位;4 位以上保持原样
  const hexFormatted = hexRaw.length < 4 ? hexRaw.padStart(4, '0') : hexRaw;

  return {
    char: char,
    decimal: code,
    hex: hexRaw,
    htmlDecimal: `&#${code};`,
    htmlHex: `&#x${hexRaw};`,
    unicodeNotation: `U+${hexFormatted}`
  };
}

// 测试
console.log(getCodePoint('A'));
console.log(getCodePoint('<'));
console.log(getCodePoint('汉'));
console.log(getCodePoint('😀'));
console.log(getCodePoint('𠮷'));

Unicode 码点 → 字符

方法1:String.fromCharCode()

仅适用于码点 ≤ 0xFFFF 的字符。

js 复制代码
const char1 = String.fromCharCode(65);
const char2 = String.fromCharCode(0x41);
const char3 = String.fromCharCode(27721);

console.log(char1);
console.log(char2);
console.log(char3);
方法2:String.fromCodePoint()

ES6 引入,支持全部 Unicode 码点。

js 复制代码
// 正确转换所有字符
const emoji = String.fromCodePoint(128512);
const rareChar = String.fromCodePoint(0x20BB7);

console.log(emoji); // 😀
console.log(rareChar); // 𠮷

// 批量转换
const codePoints = [65, 27721, 128512, 0x20BB7];
const chars = String.fromCodePoint(...codePoints);
console.log(chars);  // "A汉😀𠮷"

命名字符引用详解

历史渊源

命名字符引用的概念借鉴自 SGML 的实体机制,但仅保留了其中用于字符表示的内部实体形式。HTML 4.01 定义了 252 个命名字符引用。HTML5 进一步扩展至 2,231 个,新增内容主要为数学符号、希腊字母及其大小写变体。

必须转义的字符

以下五个字符在 HTML 中具有特殊语义,需要根据场景使用字符引用:

字符 名称 命名字符引用 数字引用 必须转义的场景
& AND 符号 &amp; &#38; 所有场景(字符引用起始符)
< 小于号 &lt; &#60; 所有场景(标签起始符)
> 大于号 &gt; &#62; 建议在所有场景中转义以确保安全
" 双引号 &quot; &#34; 双引号包裹的属性值中
' 单引号 ' &#39; 单引号包裹的属性值中

常见命名字符引用

空格类
html 复制代码
&nbsp;   <!-- U+00A0 不间断空格 (Non-Breaking Space) -->
&ensp;   <!-- U+2002 半角空格 (En Space) -->
&emsp;   <!-- U+2003 全角空格 (Em Space) -->
&thinsp; <!-- U+2009 窄空格 (Thin Space) -->
引号类
html 复制代码
&quot;      <!-- U+0022 直双引号 -->
'      <!-- U+0027 直单引号 -->
"     <!-- U+201C 左双引号 " -->
"     <!-- U+201D 右双引号 " -->
'     <!-- U+2018 左单引号 ' -->
'     <!-- U+2019 右单引号 ' -->
<<     <!-- U+00AB 左书名号 << -->
>>     <!-- U+00BB 右书名号 >> -->
数学符号
html 复制代码
&times;     <!-- U+00D7 乘号 × -->
&divide;    <!-- U+00F7 除号 ÷ -->
&plusmn;    <!-- U+00B1 正负号 ± -->
&infin;     <!-- U+221E 无穷 ∞ -->
&sum;       <!-- U+2211 求和 ∑ -->
&prod;      <!-- U+220F 求积 ∏ -->
&int;       <!-- U+222B 积分 ∫ -->
&radic;     <!-- U+221A 根号 √ -->
货币符号
html 复制代码
&cent;      <!-- U+00A2 美分 ¢ -->
&pound;     <!-- U+00A3 英镑 £ -->
&euro;      <!-- U+20AC 欧元 € -->
&yen;       <!-- U+00A5 日元 ¥ -->
箭头
html 复制代码
&larr;      <!-- U+2190 左箭头 ← -->
&uarr;      <!-- U+2191 上箭头 ↑ -->
&rarr;      <!-- U+2192 右箭头 → -->
&darr;      <!-- U+2193 下箭头 ↓ -->
&harr;      <!-- U+2194 左右箭头 ↔ -->
&crarr;     <!-- U+21B5 回车箭头 ↵ -->

数字字符引用详解

十进制与十六进制

html 复制代码
<!-- 十进制表示 -->
&#169;      <!-- © -->
&#8364;     <!-- € -->

<!-- 十六进制表示(x 前缀) -->
&#xA9;      <!-- © -->
&#x20AC;    <!-- € -->

<!-- 十六进制表示(X 前缀,同样有效) -->
&#XA9;      <!-- © -->

Unicode 码点范围

HTML5 支持所有有效的 Unicode 码点(除控制字符和替换字符外):

  • 基本多文种平面(BMP)U+0000U+FFFF
  • 辅助平面U+10000U+10FFFF
html 复制代码
<!-- Emoji 字符(超出 BMP) -->
&#x1F600;   <!-- 😀 -->
&#x1F389;   <!-- 🎉 -->

数字引用的优势

  1. 完整性:可表示任何 Unicode 字符,包括最新 Emoji
  2. 精确性:避免名称记忆错误
  3. 跨语言:不受 HTML 版本限制

为什么需要字符引用

保留字符冲突

HTML 使用特定字符作为标记语法的一部分:

html 复制代码
<!-- 错误:浏览器会解析为标签 -->
<p>开始学习 <p> 元素</p>

<!-- 正确:使用字符引用 -->
<p>开始学习 &lt;p&gt; 元素</p>

编码限制

当文档使用 ASCII 或 ISO-8859-1 编码时,无法直接表示非 ASCII 字符:

html 复制代码
<!-- 在 ASCII 编码文档中 -->
<p>版权所有 &copy; 2026</p>  <!-- 正确 -->
<p>版权所有 © 2026</p>       <!-- 可能显示为乱码 -->

不可见字符

某些控制字符或特殊空格无法直接输入:

html 复制代码
<p>A&bsp;&nbsp;B</p>

键盘不可输入字符

html 复制代码
<!-- 键盘上没有的符号 -->
<p>温度:25&deg;C</p>    <!-- 25°C -->

最佳实践

始终使用分号

html 复制代码
<!-- 推荐 -->
&lt;tag&gt;

<!-- 不推荐 -->
&lt;tag&gt

在属性值中转义引号

html 复制代码
<!-- 双引号包裹的属性 -->
<p title="He said &quot;Hello&quot;">test</p>

<!-- 单引号包裹的属性 -->
<p title='It's working'>test</p>

优先使用名称

html 复制代码
<!-- 推荐:可读性好 -->
&copy; &gt; &lt;

<!-- 不推荐:难以辨认 -->
&#169; &#62; &#60;

双重转义

html 复制代码
<p>&amp;lt;</p>   <!-- 显示为 &lt; 而不是 < -->

大小写敏感

HTML5 中命名字符引用区分大小写

html 复制代码
&copy;   <!-- 正确:© -->
&COPY;   <!-- 正确:HTML5 支持大写变体 -->
&Copy;   <!-- 错误:不存在 -->

JS 中不要使用字符引用

html 复制代码
<!-- 错误:在 script 中使用字符引用 -->
<script>
  var text = "5 &lt; 10";  // 实际字符串包含 "&lt;" 而不是 "<"
</script>

<!-- 正确:在 script 中使用 Unicode 转义或直接字符 -->
<script>
  var text = "5 < 10";     // 直接字符(如果编码支持)
  var text = "5 \u003C 10"; // JavaScript Unicode 转义
</script>

提示 :字符引用在 HTML 解析阶段被替换,<script><style> 元素的内容被视为原始文本,不解析字符引用。

URL 中的字符引用

html 复制代码
<!-- 错误:在 href 中使用字符引用 -->
<a href="https://example.com?foo=1&amp;bar=2">

<!-- 正确:URL 中应使用 URL 编码 -->
<a href="https://example.com?foo=1&bar=2">
<!-- 或 -->
<a href="https://example.com?foo=1%26bar=2">

注意 :在 HTML 属性中,& 必须转义为 &amp;,但浏览器会在发送到服务器前将其解码回 &。在 URL 路径或查询参数中,应使用 URL 编码(%26)而非 HTML 字符引用。

总结

字符引用是 HTML 解析器的内置替换机制,用 ASCII 序列表示任意 Unicode 字符。它分为命名字符引用与数字字符引用两种形式,分别解决可读性与覆盖范围的需求。&< 在所有场景下必须转义,>"' 在特定上下文中需要转义。理解字符引用的本质,就是理解 HTML 如何在纯文本层面安全地表达任意字符------这是编写兼容、健壮网页的基础。

相关推荐
matlab_xiaowang1 小时前
Redux 入门:JavaScript 可预测状态管理库
开发语言·javascript·其他·ecmascript
幼儿园技术家2 小时前
前端如何设计权限系统(RBAC / ABAC)?
前端
虹科网络安全2 小时前
艾体宝干货|数据复制详解:类型、原理与适用场景
java·开发语言·数据库
axng pmje2 小时前
Java语法进阶
java·开发语言·jvm
老前端的功夫2 小时前
【Java从入门到入土】28:Stream API:告别for循环的新时代
java·开发语言·python
qq_435287922 小时前
第9章 夸父逐日与后羿射日:死循环与进程终止?十个太阳同时值班的并行冲突
java·开发语言·git·死循环·进程终止·并行冲突·夸父逐日
止语Lab3 小时前
从手动到框架:Go DI 演进的三个拐点
开发语言·后端·golang
yaoxin5211233 小时前
397. Java 文件操作基础 - 创建常规文件与临时文件
java·开发语言·python
小短腿的代码世界3 小时前
Qt日志系统深度解析:从qDebug到企业级日志框架
开发语言·qt