在前端串接 RESTful API 或處理頁面篩選導頁時,我們經常需要將搜尋條件從 JavaScript Object 資料型態轉換為 GET 字串參數(Query String,例如 i=abc&m=Some%20value)。過去常見用 Object.keys() 搭配字串拼接的做法,不僅程式碼冗長,還容易漏掉特殊字元的 URL 編碼。本篇整理使用原生 URLSearchParams 快速轉換的標準語法,以及實務上遇到 undefined、null 與陣列時的進階處理函式。
💡 反向解析需求:如果你的需求相反,是想把網址上的
?a=1&b=2轉回物件或讀取特定參數,請參考站內另一篇 JS 解析 URL:new URL 與 URLSearchParams 屬性對照。
一、基礎用法:使用 new URLSearchParams() 一行轉換
當資料物件的屬性值皆為單純的字串或數字時,直接將該 Object 傳入 new URLSearchParams(data) 並呼叫 .toString(),瀏覽器就會自動完成鍵值組裝與 URL 百分比編碼(Percent-encoding):
const data = {
i: 'abc',
m: 'Some value',
page: 1,
};
// 直接將 Object 轉換為 GET 參數格式的字串
const params = new URLSearchParams(data).toString();
console.log(params);
// 輸出結果:
// "i=abc&m=Some+value&page=1"
ℹ️ 關於空白字元的編碼差異:依據 WHATWG
application/x-www-form-urlencoded規範,URLSearchParams.toString()會將空白字元編碼為+(例如Some+value);若後端 API 嚴格要求空白必須編碼為%20,可在結尾加上.replace(/\+/g, '%20'),或改用下方第三節的encodeURIComponent寫法。
二、實務避坑:處理 Object 中的 undefined、null 與陣列
雖然直接把物件丟進 new URLSearchParams(data) 非常方便,但在真實專案的表單篩選中,物件經常包含未填寫的 undefined、null 或多選陣列。若未先過濾就直接轉換,會踩到以下兩個常見陷阱:
undefined與null會被轉成字面字串:{ keyword: undefined, tag: null }會被轉成"keyword=undefined&tag=null",導致後端誤以為使用者搜尋"undefined"這個關鍵字!- 陣列會被強制合併為逗號字串:
{ ids: [10, 20] }會被轉成"ids=10%2C20",而非多數後端框架預期的重複同名參數ids=10&ids=20。
支援過濾空值與展開陣列的通用轉換函式
以下封裝一個可直接複製到專案工具庫(utils)的實務轉換函式,能自動剔除 undefined / null / 空字串,並將陣列正確展開為多筆同名參數:
/**
* 將 JavaScript Object 安全轉換為 GET 查詢字串參數
* @param {Record<string, any>} obj 原始參數物件
* @returns {string} 編碼後的 Query String(不含開頭問號)
*/
function objectToGetParams(obj) {
const searchParams = new URLSearchParams();
Object.entries(obj || {}).forEach(([key, value]) => {
// 1. 自動忽略 undefined、null 與空字串
if (value === undefined || value === null || value === '') {
return;
}
// 2. 若屬性值為陣列,逐一使用 append 加入同名參數 (例如 ids=10&ids=20)
if (Array.isArray(value)) {
value.forEach((item) => {
if (item !== undefined && item !== null) {
searchParams.append(key, String(item));
}
});
return;
}
// 3. 一般基本型別(字串、數字、布林值)
searchParams.append(key, String(value));
});
return searchParams.toString();
}
// 測試範例
const filterCriteria = {
i: 'abc',
m: 'Some value',
emptyField: undefined,
nullField: null,
tags: ['js', 'react'],
};
console.log(objectToGetParams(filterCriteria));
// 輸出結果:
// "i=abc&m=Some+value&tags=js&tags=react"
三、需要將空白轉為 %20 時:Object.entries + encodeURIComponent
如果你的後端簽章驗證或第三方 API 要求空白字元必須編碼為 %20(標準 RFC 3986 格式)而非 +,可以使用 Object.entries() 搭配 encodeURIComponent():
function objectToRfc3986Query(obj) {
return Object.entries(obj || {})
.filter(([, value]) => value !== undefined && value !== null && value !== '')
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`)
.join('&');
}
const data = {
i: 'abc',
m: 'Some value',
};
console.log(objectToRfc3986Query(data));
// 輸出結果:
// "i=abc&m=Some%20value"
四、三種 Object 轉 GET 參數寫法對照表
| 轉換寫法 | 空白字元編碼 | undefined / null 處理 | 適用情境 |
|---|---|---|---|
new URLSearchParams(obj).toString() | 轉為 + | 轉成 "undefined" 字串(需注意) | 屬性值皆為已知純字串/數字的簡單物件 |
自訂 objectToGetParams(obj) 迴圈 append | 轉為 + | 自動剔除空值並支援陣列展開 | 實務專案的搜尋篩選器、API 查詢參陣列裝 |
Object.entries + encodeURIComponent | 轉為 %20 | 透過 .filter() 預先剔除 | 嚴格要求 %20 編碼的第三方 API 或簽章計算 |
💡 延伸閱讀:完成 GET 參數轉換後,若要在 jQuery 或 Next.js 中發送請求與同步網址,可參考 jQuery ajax POST / GET 使用範例 以及 [前端筆記] Next.js URL 更新不刷新網頁。