Node.js:拼查询参数时,`URLSearchParams` 比手写字符串稳一点

33 次浏览5 条回复

手写 ?a=1&b=hello world 这种查询参数,遇到空格、中文、特殊符号时很容易漏掉编码。Node 自带的 URLSearchParams 可以先顶上,不用额外装包。

环境:Node.js 18+。可以建个文件 params-demo.mjs

const params = new URLSearchParams()

params.set('q', 'hello world')
params.set('tag', '开发')
params.set('page', String(2))

const url = `https://example.com/search?${params.toString()}`
console.log(url)

跑一下:

node params-demo.mjs

大概会看到:

https://example.com/search?q=hello+world&tag=%E5%BC%80%E5%8F%91&page=2

这个适合脚本里临时拼接口地址,或者调试 webhook、搜索页参数。参数多一点时,比自己一路 & 拼下去少踩坑。

这个确实比手拼稳很多。补一个小细节:如果同一个 key 需要传多个值,用 append 会比 set 合适,set 会把前面的覆盖掉。

const params = new URLSearchParams()
params.append('tag', 'node')
params.append('tag', 'tooling')
console.log(params.toString())
// tag=node&tag=tooling

写筛选条件、标签这种参数时挺常见的。

还有个容易忽略的点:如果传进来的是完整地址,可以直接用 URL 配合它改参数,少自己判断原来有没有 ?

const url = new URL('https://example.com/search?sort=old')
url.searchParams.set('q', 'hello world')
url.searchParams.set('sort', 'new')

console.log(url.toString())
// https://example.com/search?sort=new&q=hello+world

这种在脚本里给已有链接补参数时挺顺手。

隔壁空白Lv1#2

还有个容易忽略的点:如果传进来的是完整地址,可以直接用 URL 配合它改参数,少自己判断原来有没有 ?

const url = new URL('https://example.com/search?sort=old')
url.searchParams.set('q', 'hello world')
url.searchParams.set('sort', 'new')

console.log(url.toString())
// https://example.com/search?sort=new&q=hello+world

这种在脚本里给已有链接补参数时挺顺手。

再补个小坑:URLSearchParams 传对象时,值最好先自己转成字符串或过滤一下。比如 undefinednull 不会自动按“没传”处理,很容易变成字面量。

const input = { q: 'node', page: 2, empty: undefined }
const params = new URLSearchParams()

for (const [key, value] of Object.entries(input)) {
  if (value !== undefined && value !== null) {
    params.set(key, String(value))
  }
}

console.log(params.toString())
// q=node&page=2

接口参数是从表单或配置里来的时候,这个判断挺有用。

还有一种情况也挺值得注意:如果后端约定的是 tags[]=a&tags[]=b 这种格式,URLSearchParams 不会自动帮你加方括号,key 得自己写清楚。

const params = new URLSearchParams()
params.append('tags[]', 'node')
params.append('tags[]', 'web')

console.log(params.toString())
// tags%5B%5D=node&tags%5B%5D=web

看起来方括号被编码了,但服务端一般会按解码后的 key 处理。主要还是先确认接口到底吃哪种数组格式,别前端这边猜。

再加一个小点:如果要对参数做稳定排序,可以用 params.sort(),有时候拿来生成缓存 key 或签名前的字符串会方便一点。

const params = new URLSearchParams('b=2&a=1')
params.sort()
console.log(params.toString())
// a=1&b=2

不过如果接口对参数顺序有奇怪要求,就别随手排,先按它的文档来。