js對(duì)url進(jìn)行編碼解碼的多種方式對(duì)比總結(jié)
JS URL編碼解碼完全指南:解決特殊字符、中文傳輸難題
在前端開發(fā)中,URL是數(shù)據(jù)傳輸?shù)暮诵妮d體,無論是接口請(qǐng)求、參數(shù)拼接還是頁面跳轉(zhuǎn),都離不開URL的處理。但URL對(duì)字符有嚴(yán)格限制——中文、特殊符號(hào)(如&、=、空格)等直接寫入U(xiǎn)RL會(huì)導(dǎo)致解析失敗、參數(shù)錯(cuò)亂,甚至引發(fā)安全問題。JavaScript提供了4個(gè)原生API專門處理URL編碼解碼,本文將詳細(xì)拆解它們的用法、區(qū)別、適用場(chǎng)景,幫你徹底解決URL字符傳輸難題。
一、為什么需要URL編碼解碼?
URL的設(shè)計(jì)初衷是基于ASCII字符集,僅支持字母、數(shù)字和部分符號(hào)(如-、_、.、~)。當(dāng)URL中包含以下內(nèi)容時(shí),必須進(jìn)行編碼:
- 中文/非ASCII字符(如“測(cè)試”、“こんにちは”);
- 特殊功能符號(hào)(如
&(參數(shù)分隔符)、=(鍵值對(duì)分隔符)、?(查詢參數(shù)起始符)、#(錨點(diǎn)標(biāo)識(shí)符)); - 空格、
@、%等特殊字符。
編碼的本質(zhì)是將“非法字符”轉(zhuǎn)換為URL安全的“百分號(hào)編碼格式”(如中文“測(cè)”編碼后為%E6%B5%8B),解碼則是反向還原,確保數(shù)據(jù)在傳輸過程中不被篡改或解析錯(cuò)誤。
二、JS原生URL編碼解碼API詳解
JavaScript提供了4個(gè)核心API,分為兩組:encodeURI/decodeURI(針對(duì)整個(gè)URL)和encodeURIComponent/decodeURIComponent(針對(duì)URL參數(shù)),二者不可混用,否則會(huì)導(dǎo)致嚴(yán)重問題。
1. encodeURI:編碼整個(gè)URL(不破壞URL結(jié)構(gòu))
核心作用
對(duì)整個(gè)URL字符串進(jìn)行編碼,僅轉(zhuǎn)換“非法字符”,保留URL的核心結(jié)構(gòu)(如http://、https://、/、?、&、=等)。
編碼范圍
- 不編碼:字母、數(shù)字、
-、_、.、~、:、/、?、#、&、=、+; - 編碼:中文、空格、
@、%、¥等其他字符。
適用場(chǎng)景
需要編碼完整URL(如跳轉(zhuǎn)鏈接、接口請(qǐng)求地址),且URL已包含?、&等參數(shù)分隔符時(shí)。
代碼示例
// 原始URL(包含中文和空格) const originalUrl = "https://example.com/搜索?keyword=JS 教程&page=1"; // 編碼整個(gè)URL const encodedUrl = encodeURI(originalUrl); console.log(encodedUrl); // 輸出:https://example.com/%E6%90%9C%E7%B4%A2?keyword=JS%20%E6%95%99%E7%A8%8B&page=1 // 可見:中文“搜索”→%E6%90%9C%E7%B4%A2,空格→%20,而?、&、=保留不變 // 解碼(還原原始URL) const decodedUrl = decodeURI(encodedUrl); console.log(decodedUrl); // 輸出:https://example.com/搜索?keyword=JS 教程&page=1(完全還原)
2. encodeURIComponent:編碼URL參數(shù)(徹底編碼特殊字符)
核心作用
對(duì)URL中的單個(gè)參數(shù)值進(jìn)行編碼,會(huì)轉(zhuǎn)換所有“非URL安全字符”,包括?、&、=、/等原本屬于URL結(jié)構(gòu)的符號(hào)。
編碼范圍
- 不編碼:字母、數(shù)字、
-、_、.、~; - 編碼:中文、空格、
@、%、?、&、=、/、+等所有其他字符。
適用場(chǎng)景
單獨(dú)編碼URL的查詢參數(shù)(鍵或值),避免參數(shù)中包含&、=等符號(hào)導(dǎo)致參數(shù)分割錯(cuò)誤。
代碼示例
// 原始參數(shù)(包含中文、&、空格)
const keyword = "JS&CSS 教程";
const page = 1;
// 編碼單個(gè)參數(shù)(關(guān)鍵步驟)
const encodedKeyword = encodeURIComponent(keyword);
const encodedPage = encodeURIComponent(page);
// 拼接URL(參數(shù)已編碼,不會(huì)破壞結(jié)構(gòu))
const url = `https://example.com/search?keyword=${encodedKeyword}&page=${encodedPage}`;
console.log(url);
// 輸出:https://example.com/search?keyword=JS%26CSS%20%E6%95%99%E7%A8%8B&page=1
// 可見:&→%26,空格→%20,中文→%E6%95%99%E7%A8%8B,參數(shù)分割符&保留正常作用
// 解碼參數(shù)(還原原始值)
const decodedKeyword = decodeURIComponent(encodedKeyword);
console.log(decodedKeyword); // 輸出:JS&CSS 教程(完全還原)
3. decodeURI / decodeURIComponent:對(duì)應(yīng)解碼API
decodeURI:專門解碼由encodeURI編碼的URL,無法解碼encodeURIComponent編碼的&、=等符號(hào)(會(huì)報(bào)錯(cuò));decodeURIComponent:專門解碼由encodeURIComponent編碼的參數(shù),可解碼所有百分號(hào)編碼字符,是最常用的解碼方法。
錯(cuò)誤用法示例(避坑?。?/h4>
const encodedByComponent = encodeURIComponent("a&b=1"); // 編碼后:a%26b%3D1
// 錯(cuò)誤:用decodeURI解碼encodeURIComponent的結(jié)果
try {
decodeURI(encodedByComponent);
} catch (e) {
console.log(e); // 不會(huì)報(bào)錯(cuò),但解碼不完整:a&b=1(看似正常,實(shí)際特殊場(chǎng)景會(huì)出問題)
}
// 正確:用decodeURIComponent解碼
const decoded = decodeURIComponent(encodedByComponent);
console.log(decoded); // 輸出:a&b=1(完全還原)
const encodedByComponent = encodeURIComponent("a&b=1"); // 編碼后:a%26b%3D1
// 錯(cuò)誤:用decodeURI解碼encodeURIComponent的結(jié)果
try {
decodeURI(encodedByComponent);
} catch (e) {
console.log(e); // 不會(huì)報(bào)錯(cuò),但解碼不完整:a&b=1(看似正常,實(shí)際特殊場(chǎng)景會(huì)出問題)
}
// 正確:用decodeURIComponent解碼
const decoded = decodeURIComponent(encodedByComponent);
console.log(decoded); // 輸出:a&b=1(完全還原)
4. 廢棄API:escape / unescape
早期JS提供escape用于編碼,但它不遵循URL編碼標(biāo)準(zhǔn)(如中文編碼為%u6D4B%u8BD5,而非標(biāo)準(zhǔn)的%E6%B5%8B%E8%AF%95),且不支持部分特殊字符,目前已被W3C廢棄,嚴(yán)禁在項(xiàng)目中使用!
// 廢棄用法(不推薦)
const wrongEncoded = escape("測(cè)試");
console.log(wrongEncoded); // 輸出:%u6D4B%u8BD5(非標(biāo)準(zhǔn)格式,后端可能無法解析)
三、核心區(qū)別對(duì)比表(避免混用)
| API | 編碼范圍(核心差異) | 適用場(chǎng)景 | 典型錯(cuò)誤場(chǎng)景 |
|---|---|---|---|
| encodeURI | 不編碼URL結(jié)構(gòu)符(?&=/:) | 編碼完整URL | 用它編碼參數(shù)(如參數(shù)含&會(huì)分割) |
| encodeURIComponent | 編碼所有非安全字符(含?&=/:) | 編碼單個(gè)參數(shù)(鍵/值) | 用它編碼完整URL(破壞http://) |
| decodeURI | 解碼encodeURI編碼的字符 | 解碼完整URL | 解碼encodeURIComponent結(jié)果 |
| decodeURIComponent | 解碼所有百分號(hào)編碼字符 | 解碼URL參數(shù) | 解碼完整URL(可能誤解析結(jié)構(gòu)符) |
四、實(shí)際項(xiàng)目中的常見場(chǎng)景與最佳實(shí)踐
場(chǎng)景1:表單提交(參數(shù)含中文/特殊符號(hào))
// 表單數(shù)據(jù)(含中文、&、空格)
const formData = {
username: "張三&李四",
hobby: "編程 旅游",
age: 25
};
// 構(gòu)建查詢參數(shù)(關(guān)鍵:用encodeURIComponent編碼每個(gè)值)
const params = Object.entries(formData)
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
.join("&");
// 拼接完整URL(用encodeURI編碼整個(gè)URL,可選,因參數(shù)已編碼)
const requestUrl = encodeURI(`https://example.com/api/submit?${params}`);
console.log(requestUrl);
// 輸出:https://example.com/api/submit?username=%E5%BC%A0%E4%B8%89%26%E6%9D%8E%E5%9B%9B&hobby=%E7%BC%96%E7%A8%8B%20%E6%97%85%E6%B8%B8&age=25
場(chǎng)景2:解析URL參數(shù)(解碼參數(shù)值)
// 假設(shè)從地址欄獲取的URL
const url = "https://example.com/search?keyword=JS%26CSS%20%E6%95%99%E7%A8%8B&page=1";
// 提取查詢參數(shù)部分
const queryString = url.split("?")[1];
// 解析參數(shù)(解碼每個(gè)值)
const params = {};
queryString.split("&").forEach(item => {
const [key, value] = item.split("=");
params[decodeURIComponent(key)] = decodeURIComponent(value);
});
console.log(params);
// 輸出:{ keyword: 'JS&CSS 教程', page: '1' }(完全還原原始參數(shù))
場(chǎng)景3:處理URL中的錨點(diǎn)(#)
錨點(diǎn)(#)后的內(nèi)容不會(huì)發(fā)送到服務(wù)器,僅在前端生效,編碼時(shí)需注意:
const anchor = "用戶中心?tab=訂單";
// 編碼錨點(diǎn)(用encodeURIComponent,避免#后包含?&導(dǎo)致解析錯(cuò)誤)
const encodedAnchor = encodeURIComponent(anchor);
const url = `https://example.com/#${encodedAnchor}`;
console.log(url); // 輸出:https://example.com/#%E7%94%A8%E6%88%B7%E4%B8%AD%E5%BF%83%3Ftab%3D%E8%AE%A2%E5%8D%95
// 解碼錨點(diǎn)
const decodedAnchor = decodeURIComponent(url.split("#")[1]);
console.log(decodedAnchor); // 輸出:用戶中心?tab=訂單
五、避坑指南:常見問題與解決方案
問題1:參數(shù)中包含%導(dǎo)致解碼失敗
%是URL編碼的標(biāo)識(shí)符,若參數(shù)本身包含%(如百分比數(shù)據(jù)“80%”),需先編碼%為%25,否則會(huì)被誤認(rèn)為編碼字符的開頭。
const value = "80%"; const encoded = encodeURIComponent(value); console.log(encoded); // 輸出:80%25(正確編碼%) const decoded = decodeURIComponent(encoded); console.log(decoded); // 輸出:80%(正確還原)
問題2:中文編碼后后端解析亂碼
原因:前端編碼格式與后端解碼格式不一致(JS默認(rèn)用UTF-8編碼,后端若用GBK解碼會(huì)亂碼)。
解決方案:
- 前端確保用
encodeURIComponent編碼(UTF-8格式); - 后端統(tǒng)一用UTF-8解碼(如Java用
URLDecoder.decode(param, "UTF-8"),PHP用urldecode())。
問題3:參數(shù)中包含+被解析為空格
URL中+默認(rèn)被解析為空格,若參數(shù)本身需要+(如數(shù)學(xué)符號(hào)、手機(jī)號(hào)),需用encodeURIComponent編碼為%2B。
const phone = "13800138000+86"; const encoded = encodeURIComponent(phone); console.log(encoded); // 輸出:13800138000%2B86(+→%2B) const decoded = decodeURIComponent(encoded); console.log(decoded); // 輸出:13800138000+86(正確還原)
六、最佳實(shí)踐總結(jié)
- 編碼優(yōu)先級(jí):優(yōu)先使用
encodeURIComponent(參數(shù)編碼)和encodeURI(完整URL編碼),拒絕使用escape; - 參數(shù)必編碼:只要參數(shù)可能包含中文、空格、
&、=等字符,必須用encodeURIComponent編碼,再拼接URL; - 解碼對(duì)應(yīng)性:
encodeURI編碼的內(nèi)容用decodeURI解碼,encodeURIComponent編碼的內(nèi)容用decodeURIComponent解碼,不可交叉; - 后端配合:與后端約定統(tǒng)一編碼格式(UTF-8),避免跨端解析亂碼。
結(jié)語
URL編碼解碼是前端開發(fā)的“基礎(chǔ)但關(guān)鍵”技能,核心在于區(qū)分encodeURI和encodeURIComponent的適用場(chǎng)景——前者保結(jié)構(gòu),后者保參數(shù)。掌握本文的方法和避坑指南,就能輕松解決中文傳輸、參數(shù)錯(cuò)亂、特殊字符解析等問題,讓URL數(shù)據(jù)傳輸更安全、更可靠。
到此這篇關(guān)于js對(duì)url進(jìn)行編碼解碼的多種方式對(duì)比總結(jié)的文章就介紹到這了,更多相關(guān)js對(duì)url編碼解碼內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
apply和call方法定義及apply和call方法的區(qū)別
apply和call功能一樣,只是傳入的參數(shù)列表形式不同,本文給大家介紹apply和call方法定義及apply和call方法的區(qū)別,感興趣的朋友一起學(xué)習(xí)吧2015-11-11
JavaScript下載文件導(dǎo)出到本地的兩種實(shí)現(xiàn)方式
本文介紹了JavaScript中文件下載的兩種實(shí)現(xiàn)方式,瀏覽器對(duì)文件處理取決于類型和服務(wù)器的響應(yīng)頭設(shè)置,zip/docx等文件會(huì)觸發(fā)下載,而圖片/視頻等會(huì)在瀏覽器中打開,文章提供了兩種下載方案,需要的朋友可以參考下2026-02-02
面試中??嫉腏avaScript中簡單類型數(shù)據(jù)轉(zhuǎn)換盤點(diǎn)
我們都知道,JS是弱類型語言,變量的類型是可以改變的,本文我們只討論es6之前的簡單數(shù)據(jù)類型的顯示轉(zhuǎn)換String,Number,Boolean這3種,有需要的可以參考下2024-12-12
微信小程序創(chuàng)建自定義全局函數(shù)以及其調(diào)用方法詳解
微信小程序有時(shí)需要函數(shù)里面調(diào)用函數(shù),下面這篇文章主要給大家介紹了關(guān)于微信小程序創(chuàng)建自定義全局函數(shù)以及其調(diào)用方法的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下2022-09-09
JavaScript+html5 canvas制作的百花齊放效果完整實(shí)例
這篇文章主要介紹了JavaScript+html5 canvas制作的百花齊放效果,結(jié)合完整實(shí)例形式分析了使用html5的canvas技術(shù)動(dòng)態(tài)繪制圖形的技巧,需要的朋友可以參考下2016-01-01
JS模擬實(shí)現(xiàn)Excel條件格式中的色階效果
這篇文章主要為大家詳細(xì)介紹了如何利用JavaScript模擬實(shí)現(xiàn)Excel條件格式中的色階效果,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以嘗試一下2023-05-05
javascript 中事件冒泡和事件捕獲機(jī)制的詳解
這篇文章主要介紹了javascript 中事件冒泡和事件捕獲機(jī)制的詳解的相關(guān)資料,網(wǎng)上的相關(guān)資料有很多,但是講的不是多清楚,通過本文希望能讓大家理解掌握,需要的朋友可以參考下2017-09-09

