JS 原生函數行為
| 函數 | 編碼範圍 | 輸出格式 | 狀態 |
| escape() | ASCII 以外字符 | %XX (Latin-1) 或 %uXXXX (Unicode) | **已棄用** |
| unescape() | - | 還原 escape 編碼 | **已棄用** |
| encodeURIComponent() | 非保留字符 | UTF-8 %XX%XX... | **推薦** |
| decodeURIComponent() | - | 還原 | **推薦** |
PHP 模擬 escape/unescape(兼容老系統)
<?php
// 模擬 JS escape()
function jsEscape($str) {
$result = '';
$len = strlen($str);
for ($i = 0; $i < $len; $i++) {
$c = $str[$i];
$ord = ord($c);
if ($ord < 128) { // ASCII
$result .= '%' . strtoupper(dechex($ord));
} else { // 非 ASCII,按 GBK 雙字節處理(視項目編碼)
// 此處假設源字符串為 GBK
if ($i + 1 < $len) {
$char = $str[$i] . $str[$i+1];
$ucs2 = iconv('GBK', 'UCS-2BE', $char);
$hex = bin2hex($ucs2);
$result .= '%u' . $hex;
$i++;
}
}
}
return $result;
}
// 模擬 JS unescape()
function jsUnescape($str) {
// 先處理 %uXXXX
$str = preg_replace_callback('/%u([0-9A-F]{4})/i', function($m) {
return iconv('UCS-2BE', 'GBK', hex2bin($m[1]));
}, $str);
// 再處理 %XX
return rawurldecode($str);
}
// 測試
$original = '中文test';
$encoded = jsEscape($original); // %u4E2D%u6587%74%65%73%74
$decoded = jsUnescape($encoded); // 中文test
?>
現代最佳實踐:統一使用 UTF-8 + encodeURIComponent
// 前端
const encoded = encodeURIComponent('中文test'); // %E4%B8%AD%E6%96%87test
// 後端 PHP 直接接收 $_GET/$_POST 已自動解碼
// 手動解碼
$decoded = urldecode($encoded); // 中文test (UTF-8)
// 若需生成 JS 兼容編碼(如簽名算法)
function phpRawUrlEncode($str) {
return str_replace('%7E', '~', rawurlencode($str)); // RFC 3986
}
?>
編碼選型決策樹
- **新項目/現代化改造** → 強制 UTF-8,前端
encodeURIComponent,後端 rawurldecode/自動解碼。
- **維護老 GBK 項目** → 封裝
jsEscape/jsUnescape 工具類隔離編碼邏輯,逐步遷移核心接口至 UTF-8。
- **URL 參數傳遞** → 始終使用
http_build_query (PHP) / URLSearchParams (JS) 構建,避免手動拼接。
- **Cookie 存儲中文** → 必須
encodeURIComponent,Cookie 規範禁止非 ASCII 字符。