encodeURIComponent()

Baseline Widely available

This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015.

encodeURIComponent() 函数通过将特定字符的每个实例替换成代表字符的 UTF-8 编码的一个、两个、三个或四个转义序列来编码 URI(只有由两个“代理”字符组成的字符会被编码为四个转义序列)。与 encodeURI() 相比,此函数会编码更多的字符,包括 URI 语法的一部分。

尝试一下

// Encodes characters such as ?,=,/,&,:
console.log(`?x=${encodeURIComponent("test?")}`);
// Expected output: "?x=test%3F"

console.log(`?x=${encodeURIComponent("шеллы")}`);
// Expected output: "?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B"

语法

encodeURIComponent(str);

参数

uriComponent

一个 string、number、boolean、null,undefined 或者任何 object。在编码之前,uriComponent 参数会被转化为字符串。

返回值

原字串作为 URI 组成部分被被编码后的新字符串。

描述

encodeURIComponent 转义除了如下所示外的所有字符:

不转义的字符:
    A-Z a-z 0-9 - _ . ! ~ * ' ( )

encodeURIComponent()encodeURI 有以下几个不同点:

js
var set1 = ";,/?:@&=+$"; // 保留字符
var set2 = "-_.!~*'()"; // 不转义字符
var set3 = "#"; // 数字标志
var set4 = "ABC abc 123"; // 字母数字字符和空格

console.log(encodeURI(set1)); // ;,/?:@&=+$
console.log(encodeURI(set2)); // -_.!~*'()
console.log(encodeURI(set3)); // #
console.log(encodeURI(set4)); // ABC%20abc%20123 (空格被编码为 %20)

console.log(encodeURIComponent(set1)); // %3B%2C%2F%3F%3A%40%26%3D%2B%24
console.log(encodeURIComponent(set2)); // -_.!~*'()
console.log(encodeURIComponent(set3)); // %23
console.log(encodeURIComponent(set4)); // ABC%20abc%20123 (空格被编码为 %20)

注意,如果试图编码一个非高 - 低位完整的代理字符,将会抛出一个 URIError 错误,例如:

js
// 高低位完整
alert(encodeURIComponent("\uD800\uDFFF"));

// 只有高位,将抛出"URIError: malformed URI sequence"
alert(encodeURIComponent("\uD800"));

// 只有低位,将抛出"URIError: malformed URI sequence"
alert(encodeURIComponent("\uDFFF"));

为了避免服务器收到不可预知的请求,对任何用户输入的作为 URI 部分的内容你都需要用 encodeURIComponent 进行转义。比如,一个用户可能会输入"Thyme &time=again"作为comment变量的一部分。如果不使用 encodeURIComponent 对此内容进行转义,服务器得到的将是comment=Thyme%20&time=again。请注意,"&"符号和"="符号产生了一个新的键值对,所以服务器得到两个键值对(一个键值对是comment=Thyme,另一个则是time=again),而不是一个键值对。

对于 application/x-www-form-urlencoded (POST) 这种数据方式,空格需要被替换成 '+',所以通常使用 encodeURIComponent 的时候还会把 "%20" 替换为 "+"。

为了更严格的遵循 RFC 3986(它保留 !, ', (, ), 和 *),即使这些字符并没有正式划定 URI 的用途,下面这种方式是比较安全的:

js
function fixedEncodeURIComponent(str) {
  return encodeURIComponent(str).replace(/[!'()*]/g, function (c) {
    return "%" + c.charCodeAt(0).toString(16).toUpperCase();
  });
}

示例

下面这个例子提供了 UTF-8 下 Content-DispositionLink 的服务器响应头信息的参数(例如 UTF-8 文件名):

js
var fileName = "my file(2).txt";
var header =
  "Content-Disposition: attachment; filename*=UTF-8''" +
  encodeRFC5987ValueChars(fileName);

console.log(header);
// 输出 "Content-Disposition: attachment; filename*=UTF-8''my%20file%282%29.txt"

function encodeRFC5987ValueChars(str) {
  return (
    encodeURIComponent(str)
      // 注意,尽管 RFC3986 保留 "!",但 RFC5987 并没有
      // 所以我们并不需要过滤它。
      .replace(/['()]/g, escape) // i.e., %27 %28 %29
      .replace(/\*/g, "%2A")
      // 下面的并不是 RFC5987 中 URI 编码必须的
      // 所以对于 |`^ 这 3 个字符我们可以稍稍提高一点可读性
      .replace(/%(?:7C|60|5E)/g, unescape)
  );
}

// 以下是上述功能的替换方案
function encodeRFC5987ValueChars2(str) {
  return (
    encodeURIComponent(str)
      // 注意,尽管 RFC3986 保留 "!",但 RFC5987 并没有,
      // 所以我们并不需要过滤它。
      .replace(/['()*]/g, (c) => "%" + c.charCodeAt(0).toString(16)) // i.e., %27 %28 %29 %2a (请注意,"*" 的有效编码是 %2A
      // 这需要调用 toUpperCase() 方法来正确编码)
      // 以下并不是 RFC5987 编码所必须的,
      // 这样我们可以让 |`^ 在网络上获取更好的可读性
      .replace(/%(7C|60|5E)/g, (str, hex) =>
        String.fromCharCode(parseInt(hex, 16)),
      )
  );
}

规范

Specification
ECMAScript® 2025 Language Specification
# sec-encodeuricomponent-uricomponent

浏览器兼容性

Report problems with this compatibility data on GitHub
desktopmobileserver
Chrome
Edge
Firefox
Opera
Safari
Chrome Android
Firefox for Android
Opera Android
Safari on iOS
Samsung Internet
WebView Android
WebView on iOS
Deno
Node.js
encodeURIComponent

Legend

Tip: you can click/tap on a cell for more information.

Full support
Full support

参见