何时应使用 escape 而非 encodeURI / encodeURIComponent?

何时应使用 escape 而非 encodeURI / encodeURIComponent?

技术背景

在 JavaScript 中,处理字符串的 URL 编码有三个常用函数:escape()encodeURI()encodeURIComponent()。不同的函数有不同的编码规则和使用场景,了解它们之间的区别有助于开发者正确处理 URL 编码。

实现步骤

1. escape()

  • 使用建议:不建议使用该函数。escape() 已被弃用,其定义在相关规范的附录中,该附录指出其中的特性存在不良特征,在没有遗留使用的情况下应从规范中移除。
  • 编码规则:除了 @*_+-./ 外,特殊字符都会被编码。对于代码单元值为 0xFF 或更小的字符,使用两位十六进制转义序列 %xx;对于代码单元值更大的字符,使用四位格式 %uxxxx,但这种格式在查询字符串中不被允许。

2. encodeURI()

  • 使用场景:当你想要一个有效的完整 URL 时使用。
  • 编码规则:不会编码 ~!@#$&*()=:/,;?+' 这些字符,它会保留 URI 的结构,不会对具有特殊含义的保留字符进行编码。
  • 示例
1
2
console.log(encodeURI("http://www.example.org/a file with spaces.html")); 
// 输出: http://www.example.org/a%20file%20with%20spaces.html

3. encodeURIComponent()

  • 使用场景:当你想要对 URL 参数的值进行编码时使用。
  • 编码规则:不会编码 - _ . ! ~ * ' ( ) 这些字符,它会对传入的字符串进行全面编码,忽略 URI 的结构。
  • 示例
1
2
3
4
var p1 = encodeURIComponent("http://example.org/?a=12&b=55");
var url = "http://example.net/?param1=" + p1 + "&param2=99";
console.log(url);
// 输出: http://example.net/?param1=http%3A%2F%2Fexample.org%2F%3Fa%3D12%26b%3D55&param2=99

核心代码

生成 encodeURI()encodeURIComponent() 编码差异的表格

1
2
3
4
5
6
7
8
9
10
11
12
var arr = [];
for(var i = 0; i < 256; i++) {
var char = String.fromCharCode(i);
if(encodeURI(char) !== encodeURIComponent(char)) {
arr.push({
character: char,
encodeURI: encodeURI(char),
encodeURIComponent: encodeURIComponent(char)
});
}
}
console.table(arr);

自定义编码和解码函数

1
2
3
4
5
6
7
8
9
10
11
function encodeData(s) {
return encodeURIComponent(s).replace(/\-/g, "%2D").replace(/\_/g, "%5F").replace(/\./g, "%2E").replace(/\!/g, "%21").replace(/\~/g, "%7E").replace(/\*/g, "%2A").replace(/\'/g, "%27").replace(/\(/g, "%28").replace(/\)/g, "%29");
}

function decodeData(s) {
try {
return decodeURIComponent(s.replace(/\%2D/g, "-").replace(/\%5F/g, "_").replace(/\%2E/g, ".").replace(/\%21/g, "!").replace(/\%7E/g, "~").replace(/\%2A/g, "*").replace(/\%27/g, "'").replace(/\%28/g, "(").replace(/\%29/g, ")"));
} catch (e) {
}
return "";
}

修正的 encodeURI()encodeURIComponent() 函数

1
2
3
4
5
6
7
8
9
function fixedEncodeURI(str) {
return encodeURI(str).replace(/%5B/g, '[').replace(/%5D/g, ']');
}

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

最佳实践

  • 使用 encodeURIComponent() 处理 URL 参数:在拼接 URL 参数时,使用 encodeURIComponent() 对参数值进行编码,以避免参数值中的特殊字符影响 URL 的正确性。
1
2
var user_input = "some special characters @#$%^&*";
var url = "https://example.com/upload?input=" + encodeURIComponent(user_input);
  • 避免使用 encodeURI():由于 encodeURI() 可能会导致一些字符未被正确编码,建议使用修正后的 fixedEncodeURI() 函数。
  • 使用 escape() 的场景:仅当数据仅用于 JavaScript 解析时,如在 URI 的哈希部分,可以使用 escape()。但由于其已被弃用,使用时需谨慎。

常见问题

1. encodeURIComponent() 未对 * 进行编码

encodeURIComponent() 不会对 - _ . ! ~ * ' ( ) 这些字符进行编码,这可能会导致问题。可以使用修正后的 fixedEncodeURIComponent() 函数来解决。

2. decodeURIComponent() 未正确解码 +

decodeURIComponent() 不会将 + 解码为空格,需要手动处理。可以在编码时将 + 替换为 %2B

3. 编码函数对单独代理项的处理

encodeURI()encodeURIComponent() 在遇到单独代理项(0xD800 - 0xDFFFF)时会抛出 URIError,而 escape() 不会,它会将其编码为 %uXXXX 格式。


何时应使用 escape 而非 encodeURI / encodeURIComponent?
https://119291.xyz/posts/when-to-use-escape-instead-of-encodeuri-or-encodeuricomponent/
作者
ww
发布于
2025年6月6日
许可协议