JavaScript阅读约 7 分钟

encodeURI 和 encodeURIComponent 有什么区别?

encodeURI 用于编码完整的 URL,会保留 /、? 和 # 等结构性字符。encodeURIComponent 用于编码单个 URI 组成部分,会对包括 /、? 和 & 在内的所有特殊字符进行编码。查询参数值应使用 encodeURIComponent,完整 URL 应使用 encodeURI。

什么是 encodeURI()?

encodeURI() 是 JavaScript 的内置函数,用于编码一个完整的统一资源标识符(URI)。它会把在 URI 中不合法的字符转换为对应的 percent-encoding 形式,但会有意保留那些在 URI 中具有结构含义的字符。

具体来说,encodeURI() 不会编码以下字符:A-Z a-z 0-9 ; , / ? : @ & = + $ - _ . ! ~ * ' ( ) #。这意味着编码之后 URL 的整体结构依然保持完整。

// encodeURI() 会保留 URL 结构
const url = 'https://example.com/my page?name=John Doe&city=New York';
console.log(encodeURI(url));
// "https://example.com/my%20page?name=John%20Doe&city=New%20York"
// 注意::、/、?、& 和 = 都没有被编码

正是这种行为,使得 encodeURI() 非常适合处理这样一种情形:你有一个完整的 URL,其中可能包含空格或非 ASCII 字符,但其结构性字符(协议分隔符、路径分隔符、查询字符串标记)应当原样保留。

什么是 encodeURIComponent()?

encodeURIComponent() 用于编码 URI 的单个组成部分,例如查询参数值或路径片段。与 encodeURI() 不同,它几乎会编码所有特殊字符,包括那些在 URL 中具有结构含义的字符。

encodeURIComponent() 唯一不会编码的字符是:A-Z a-z 0-9 - _ . ! ~ * ' ( )。除此之外的所有字符,包括 /?&=#:,都会被进行 percent-encoding。

// encodeURIComponent() 会编码除非保留字符之外的所有字符
const value = 'Tom & Jerry / Friends?';
console.log(encodeURIComponent(value));
// "Tom%20%26%20Jerry%20%2F%20Friends%3F"
// 注意:&、/ 和 ? 都被编码了

// 构建带查询参数的 URL
const url = 'https://example.com/search?q=' + encodeURIComponent(value);
// "https://example.com/search?q=Tom%20%26%20Jerry%20%2F%20Friends%3F"

由于它会编码结构性字符,因此你绝不应该对一个完整的 URL 使用 encodeURIComponent()。这样做会把 ://、所有 / 路径分隔符以及 ? 查询分隔符全部编码掉,导致 URL 无法使用。

核心区别一览

特性 encodeURI() encodeURIComponent()
用途 编码完整的 URI 编码 URI 的组成部分
编码 / 是(%2F
编码 ? 是(%3F
编码 & 是(%26
编码 = 是(%3D
编码 # 是(%23
编码 : 是(%3A
编码空格 是(%20 是(%20
编码 Unicode

何时使用哪个函数

规则很简单:当你想编码一个完整 URL 并保持其结构有效时,使用 encodeURI();当你想编码将要插入到 URL 中的单个值时,使用 encodeURIComponent()

// 场景 1:编码包含空格的完整 URL
const fullUrl = 'https://example.com/my documents/file name.pdf';
const encoded = encodeURI(fullUrl);
// "https://example.com/my%20documents/file%20name.pdf"

// 场景 2:从各部分拼接构建 URL
const baseUrl = 'https://api.example.com/search';
const query = 'price >= 100 & category = books';
const finalUrl = baseUrl + '?q=' + encodeURIComponent(query);
// "https://api.example.com/search?q=price%20%3E%3D%20100%20%26%20category%20%3D%20books"

// 场景 3:将重定向 URL 作为参数进行编码
const redirectUrl = 'https://example.com/callback?token=abc';
const loginUrl = 'https://auth.example.com/login?redirect=' +
  encodeURIComponent(redirectUrl);
// 整个重定向 URL 被作为单个参数值进行编码

常见错误及如何避免

错误 1:用 encodeURI() 编码查询参数值。 由于 encodeURI() 不会编码 &=,因此在包含这些字符的参数值上使用它,会破坏查询字符串的结构。

// 错误做法
const bad = 'https://example.com/search?q=' + encodeURI('salt & pepper');
// "https://example.com/search?q=salt%20&%20pepper"
// 服务器看到的是 q="salt " 以及一个额外的参数 " pepper"

// 正确做法
const good = 'https://example.com/search?q=' + encodeURIComponent('salt & pepper');
// "https://example.com/search?q=salt%20%26%20pepper"

错误 2:对完整 URL 使用 encodeURIComponent()。 这会把所有斜杠、冒号和问号都编码掉,从而破坏 URL 结构。

// 错误做法
console.log(encodeURIComponent('https://example.com/path?key=value'));
// "https%3A%2F%2Fexample.com%2Fpath%3Fkey%3Dvalue"
// 这已经不是一个有效的 URL 了!

// 正确做法
console.log(encodeURI('https://example.com/path?key=value'));
// "https://example.com/path?key=value"(本身已经有效,没有需要编码的字符)

错误 3:重复编码。 如果一个字符串已经过 percent-encoding,再次编码就会把其中的 % 符号也编码掉,从而将 %20 变成 %2520。在应用编码函数之前,请务必检查该值是否已经被编码过。

一个更安全的现代替代方案是使用 URLURLSearchParams API,它们会自动处理编码,帮你彻底避开这些陷阱。

相关文章

试用我们的免费工具