一、概念
在前端开发中,URL 编码是常见操作。JavaScript 提供了四个相关方法:
encodeURI:对整个 URI 进行编码。encodeURIComponent:对 URI 片段(组件)进行编码。decodeURI:对encodeURI编码的结果进行解码。decodeURIComponent:对encodeURIComponent编码的结果进行解码。
简而言之:
encodeURI/decodeURI用在完整 URL 层级。encodeURIComponent/decodeURIComponent用在 URL 中的参数或单独片段。
二、原理
- URL 编码的目的
URL 只能使用 ASCII 字符(安全子集),因此像空格、中文、特殊符号(如?、&、=)必须转换为合法形式。
比如:空格 → %20,中 → %E4%B8%AD。 encodeURI的编码规则
保留了 URL 中合法的结构符号:
- 不会转义
: / ? # & =等(这些在 URL 中有语义作用)。 - 会转义空格、中文、非法符号。
encodeURIComponent的编码规则
它比encodeURI更严格:
- 几乎所有非字母数字字符都会被转义,包括
? & =等。 - 因此适合用于参数值的编码,避免与 URL 本身结构冲突。
- 解码函数
decodeURI只会解码encodeURI编码的字符串。decodeURIComponent更“彻底”,可以解码参数中的转义内容。
三、对比
| 方法 | 适用范围 | 保留字符 | 示例 |
|---|---|---|---|
| encodeURI | 整个 URL | : / ? # & = 等结构符号 | encodeURI("https://a.com?q=测试") → "https://a.com?q=%E6%B5%8B%E8%AF%95" |
| encodeURIComponent | URL 片段 / 参数 | 不保留任何结构符号 | encodeURIComponent("测试&demo") → "%E6%B5%8B%E8%AF%95%26demo" |
| decodeURI | 解码 encodeURI 的结果 | 保留结构符号 | decodeURI("https://a.com?q=%E6%B5%8B%E8%AF%95") → "https://a.com?q=测试" |
| decodeURIComponent | 解码 encodeURIComponent 的结果 | 更彻底 | decodeURIComponent("%E6%B5%8B%E8%AF%95%26demo") → "测试&demo" |
四、实践
1. 错误示例
// 错误:encodeURIComponent 编码整个 URL
let url = "https://example.com/page?q=hello world";
let wrong = encodeURIComponent(url);
console.log(wrong);
// 输出: "https%3A%2F%2Fexample.com%2Fpage%3Fq%3Dhello%20world"
// 问题:整个 URL 都被转义,浏览器无法识别
2. 正确用法
// 正确:encodeURI 用于整个 URL
let url = "https://example.com/page?q=hello world";
let correct = encodeURI(url);
console.log(correct);
// 输出: "https://example.com/page?q=hello%20world"
// 正确:encodeURIComponent 用于参数值
let param = "hello world&测试";
let encodedParam = encodeURIComponent(param);
let finalUrl = `https://example.com/page?q=${encodedParam}`;
console.log(finalUrl);
// 输出: "https://example.com/page?q=hello%20world%26%E6%B5%8B%E8%AF%95"
五、拓展
-
为什么要区分 URI 与 URI Component?
- URI(统一资源标识符)由多个部分组成,如协议、主机名、路径、查询参数。
- 如果把整个 URL 都用
encodeURIComponent,结构符号也被转义,URL 失效。 - 所以规范上才有这两个不同层级的方法。
-
配合使用场景
- 构造 API 请求时,
encodeURIComponent是必需的,否则特殊字符会导致参数错位。 - 解析 URL 时,必须选择和编码阶段对应的解码函数,否则会解码不完整或报错。
- 构造 API 请求时,
-
与 escape/unescape 的区别
- 旧方法
escape/unescape已弃用,不支持完整的 UTF-8 编码。 - 应始终使用
encodeURI系列。
- 旧方法
六、潜在问题
-
双重编码问题
- 如果某个参数已经被编码,再次用
encodeURIComponent,会出现%25(即%的转义)。 - 解决:只在拼接 URL 时编码一次。
- 如果某个参数已经被编码,再次用
-
解码不匹配
-
decodeURI解码encodeURIComponent的结果时,可能失败或解码不完整。 -
必须成对使用:
encodeURI↔decodeURIencodeURIComponent↔decodeURIComponent
-
-
兼容性问题
- 现代浏览器已统一支持这四个方法,但在部分旧代码库里仍存在
escape/unescape,需要注意迁移。
- 现代浏览器已统一支持这四个方法,但在部分旧代码库里仍存在
✅ 总结一句:
- 整个 URL →
encodeURI - 参数值 →
encodeURIComponent - 解码时严格配对使用
本文部分内容借助 AI 辅助生成,并由作者整理审核。