前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
  • 基础篇

    • 环境搭建
    • node部署
    • 基础应用
  • 内置模块

    • 1.0 本地路径处理 path
    • 2.0 文件系统操作 fs
    • 3.1 基础调试 console
    • 3.2 本地调试远程服务器上的Node代码
    • 4.1 网络服务 http
    • 4.2 网络服务 http res
    • 4.3 网络服务 http req
    • 4.4 网络服务 http server
    • 4.5 网络服务 http client
    • 4.6 网络服务 https
    • 4.7 网络TCP net
    • 4.8 网络UDP dgram
    • 4.9 域名解析 dns
    • 5.0 网络地址解析 url
    • 5.1 URL查询字符串 querystring
    • 6.1 流操作 stream
    • 6.2 逐行读取 readline
    • 7.1 进程相关 process
    • 7.2 子进程 child
    • 8.1 二进制数据 buffer
    • 8.2 二进制解码 string_decoder
    • 9.1 事件机制 events
    • 9.2 实用工具模块 util
    • 9.3 数据加密 crypto
    • 9.4 MD5入门介绍及crypto模块的应用
    • 9.4 资源压缩 zlib
    • 9.5 集群 cluster
    • 9.6 v8
  • 进阶篇

    • 5分钟入门非对称加密用法
    • cluster
    • cookie_parser深入
    • crypto模块之理论篇
    • express+cookie_parser签名机制深入剖析
    • express+session实现简易身份认证
    • https
    • log4js入门实例
    • node8_napi
    • 使用 async 控制并发
    • 使用 eventproxy 控制并发
    • 使用 superagent 与 cheerio 完成简单爬虫
    • 基于express+muter的文件上传
    • 将图片转成datauri嵌入到html
    • 常用中间件 body_parser 实现解析
    • 日志模块morgan
    • 服务端字符编解码&乱码处理 charset_enc_dec
    • 测试用例mocha,should,istanbul
    • 调试日志打印debug模块
  • Express

    • 1.1 Express概览篇
    • 1.2 Express
  • Koa2

    • 1.0 koa2概览篇
    • 1.1 快速开始
    • 1.2 async await使用
    • 1.3 koa2简析结构
    • 1.4 koa中间件开发与使用
    • 10.1 单元测试
    • 11.1 开发debug
    • 12.1 快速启动
    • 12.2 框架设计
    • 12.3 分层操作
    • 12.4 数据库设计
    • 12.5 路由设计
    • 12.6 webpack4环境搭建
    • 12.7 使用react
    • 12.8 登录注册功能实现
    • 12.9 session登录态判断处理
    • 13.1 import export使用
    • 2.1 原生koa2实现路由
    • 2.2 koa router中间
    • 3.1 GET请求数据获取
    • 3.2 POST请求数据获取
    • 3.3 koa bodyparser中间件
    • 4.1 原生koa2实现静态资源服务器
    • 4.2 koa static中间件
    • 5.1 koa2使用cookie
    • 5.2 koa2实现session
    • 6.1 koa2加载模板引擎
    • 6.2 ejs模板引擎
    • 7.1 busboy模块
    • 7.2 上传文件简单实现
    • 7.3 异步上传图片实现
    • 8.1 mysql模块
    • 8.2 async await封装使用mysql
    • 8.3 项目建表初始化
    • 9.1 原生koa2实现JSONP
    • 9.2 koa jsonp中间件
  • 其他

    • 操作数据库
    • Session 与 Token
    • Cookie、Session、Token、JWT
    • Socket

# URL查询字符串 querystring

30 秒速记

  • querystring 是 Node.js 老模块,官方标了 legacy;新代码用全局的 URLSearchParams
  • 重复键:querystring.parse 给数组,URLSearchParams 用 get 拿第一个、getAll 拿全部
  • 值永远是字符串,page=2 拿到的是 '2',数字布尔要自己转
  • 空格编码不同:querystring 是 %20,URLSearchParams 是 +
  • querystring.parse 默认最多解析 1000 个键(maxKeys),防恶意超长参数

查询字符串就是 ? 后面那串 a=1&b=2,Node.js 里老办法是 querystring 模块,新办法是 URLSearchParams。 两者都能解析和拼接,但细节不同:重复键 querystring 直接给数组,URLSearchParams 要用 getAll;空格一个编成 %20、一个编成 +。不管用哪个,拿到的值都是字符串,page=2 拿到 '2',直接相加就变成字符串拼接。所以我在接口入口一定会配一层 schema 校验,把类型、默认值、是否允许多值都定下来。

理解「URL查询字符串 querystring」时,要先明确输入、运行阶段和可观察输出。这里的交互实验会分别执行正常路径与失败路径,并把 Node.js 的关键状态变化和同屏代码对应起来;不能只记命令名称。

工程中还要验证退出码、资源清理和异常输入。属于 buffer 场景的配置应保持最小可复现,并在开发环境与 CI 中使用相同命令复跑,避免把平台差异或隐式默认值带到线上。

面试官追问

追问 1?tag=js&tag=node,querystring.parse 和 URLSearchParams 各拿到什么?
参考回答

querystring.parse 得到 { tag: ['js', 'node'] };URLSearchParams 的 get('tag') 是 'js',getAll('tag') 是两个都有。要是用 Object.fromEntries(params) 转对象,只剩最后一个 'node'。

追问 2筛选接口有时收到字符串、有时收到数组,代码一会儿正常一会儿报错,怎么治?
参考回答

这是重复键导致的类型不稳定。入口统一规整:[].concat(q.tag ?? []) 永远转数组,或者用 getAll。更好的是用 zod 这类 schema 明确每个字段是单值还是多值。

追问 3?debug=false,代码里 if (q.debug) 却进了分支,为什么?
参考回答

'false' 是非空字符串,是真值。查询参数要显式转换,比如 q.debug === 'true',别依赖 JS 的真假值判断。

追问 4有人传了几万个参数的超长查询串,服务会不会被拖垮?
参考回答

querystring.parse 默认 maxKeys 是 1000,超出部分直接丢掉,能挡一部分。但更该在网关或框架层限制 URL 总长度,Node.js 本身对请求头总大小默认也有约 16KB 的上限。

# 模块概述

30 秒速记

  • querystring 四个方法:parse、stringify、escape、unescape,日常只用前两个
  • parse:字符串 → 对象;stringify:对象 → 字符串
  • parse 返回的对象没有原型,obj.hasOwnProperty 会报错
  • 不做嵌套:a[b]=1 解析出的键就是 'a[b]',要嵌套用 qs 库
  • decode / encode 是 parse / stringify 的别名

querystring 是 Node.js 处理查询参数的老模块,核心就两个方法:parse 把字符串解析成对象,stringify 反过来。 用起来很简单,但有两个细节常被问。一是 parse 返回的对象是用 Object.create(null) 造的,没有原型,obj.hasOwnProperty('a') 直接报错,要用 Object.hasOwn(obj, 'a')。二是它不支持嵌套,user[name]=tom 解析出来键名就是 'user[name]',Express 能解析嵌套是因为默认用了 qs 库。

在nodejs中,提供了querystring这个模块,用来做url查询参数的解析,使用非常简单。

模块总共有四个方法,绝大部分时,我们只会用到 .parse()、 **.stringify()**两个方法。剩余的方法,感兴趣的同学可自行查看文档。

  • .parse():对url查询参数(字符串)进行解析,生成易于分析的json格式。
  • .stringif():跟**.parse()**相反,用于拼接查询查询。
querystring.parse(str[, sep[, eq[, options]]])
querystring.stringify(obj[, sep[, eq[, options]]])
@前端进阶之旅: 代码已经复制到剪贴板

面试官追问

追问 1querystring.parse(str).hasOwnProperty('a') 报 is not a function,为什么?
参考回答

返回的对象没有原型,自然没有 hasOwnProperty。改成 Object.hasOwn(obj, 'a') 或 'a' in obj。这样设计是为了防止 ?__proto__=x 这类参数污染原型。

追问 2前端传 user[name]=tom&user[age]=18,querystring 能解析成嵌套对象吗?
参考回答

不能,得到的是 { 'user[name]': 'tom', 'user[age]': '18' }。要嵌套就用 qs,不过嵌套查询串本身就容易引发原型污染和类型混乱,复杂结构我更倾向放到 POST 的 JSON 里。

追问 3querystring.parse('a=1+2') 拿到的 a 是什么?
参考回答

'1 2',+ 会被当成空格解码。如果值里真要一个加号,传的时候得编码成 %2B。

追问 4querystring 和 URLSearchParams,新项目选哪个?
参考回答

选 URLSearchParams,浏览器和 Node.js 都是全局可用,前后端一套写法。querystring 唯一的优势是能自定义分隔符,对接非标准格式时才用得上。

# 查询参数解析:querystring.parse()

30 秒速记

  • querystring.parse(str, sep = '&', eq = '=', options)
  • 'nick=casper&age=24' → { nick: 'casper', age: '24' },age 是字符串
  • sep / eq 换分隔符:parse('name-chyingp|country-cn', '|', '-') 也能解析
  • options.maxKeys 默认 1000,传 0 不限;options.decodeURIComponent 可换解码函数
  • 边界:a → { a: '' },a= → { a: '' },重复键 → 数组

querystring.parse 把 a=1&b=2 这种字符串拆成对象,默认用 & 分参数、= 分键值。 第二三个参数可以换掉这两个符号,适合对接 name-chyingp|country-cn 这种自定义格式,不用自己写两层 split。第四个参数用得少,主要是 maxKeys,默认只解析前 1000 个键。要记住的是它不做类型推断,age=24 拿到的是字符串 '24',空值和没写等号都是空字符串,重复键会变成数组。

参数:querystring.parse(str[, sep[, eq[, options]]])

第四个参数几乎不会用到,直接不讨论. 第二个, 第三个其实也很少用到,但某些时候还是可以用一下。直接看例子

var querystring = require('querystring');
var str = 'nick=casper&age=24';
var obj = querystring.parse(str);
console.log(JSON.stringify(obj, null, 4));
@前端进阶之旅: 代码已经复制到剪贴板

输出如下

{
    "nick": "casper",
    "age": "24"
}
@前端进阶之旅: 代码已经复制到剪贴板

再来看下sep、eq有什么作用。相当于可以替换&、=为自定义字符,对于下面的场景来说还是挺省事的。

var str1 = 'nick=casper&age=24&extra=name-chyingp|country-cn';
var obj1 = querystring.parse(str1);
var obj2 = querystring.parse(obj1.extra, '|', '-');
console.log(JSON.stringify(obj2, null, 4));
@前端进阶之旅: 代码已经复制到剪贴板

输出如下

{
    "name": "chyingp",
    "country": "cn"
}
@前端进阶之旅: 代码已经复制到剪贴板

面试官追问

追问 1age=24 解析出来直接 obj.age + 1,结果是 '241',怎么改?
参考回答

parse 只拆字符串不转类型,要显式 Number(obj.age),并且判断 Number.isNaN

基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
  • 基础篇

    • 环境搭建
    • node部署
    • 基础应用
  • 内置模块

    • 1.0 本地路径处理 path
    • 2.0 文件系统操作 fs
    • 3.1 基础调试 console
    • 3.2 本地调试远程服务器上的Node代码
    • 4.1 网络服务 http
    • 4.2 网络服务 http res
    • 4.3 网络服务 http req
    • 4.4 网络服务 http server
    • 4.5 网络服务 http client
    • 4.6 网络服务 https
    • 4.7 网络TCP net
    • 4.8 网络UDP dgram
    • 4.9 域名解析 dns
    • 5.0 网络地址解析 url
    • 5.1 URL查询字符串 querystring
      • 模块概述
      • 查询参数解析:querystring.parse()
      • 查询参数拼接:querystring.stringify()
      • 相关链接
    • 6.1 流操作 stream
    • 6.2 逐行读取 readline
    • 7.1 进程相关 process
    • 7.2 子进程 child
    • 8.1 二进制数据 buffer
    • 8.2 二进制解码 string_decoder
    • 9.1 事件机制 events
    • 9.2 实用工具模块 util
    • 9.3 数据加密 crypto
    • 9.4 MD5入门介绍及crypto模块的应用
    • 9.4 资源压缩 zlib
    • 9.5 集群 cluster
    • 9.6 v8
  • 进阶篇

    • 5分钟入门非对称加密用法
    • cluster
    • cookie_parser深入
    • crypto模块之理论篇
    • express+cookie_parser签名机制深入剖析
    • express+session实现简易身份认证
    • https
    • log4js入门实例
    • node8_napi
    • 使用 async 控制并发
    • 使用 eventproxy 控制并发
    • 使用 superagent 与 cheerio 完成简单爬虫
    • 基于express+muter的文件上传
    • 将图片转成datauri嵌入到html
    • 常用中间件 body_parser 实现解析
    • 日志模块morgan
    • 服务端字符编解码&乱码处理 charset_enc_dec
    • 测试用例mocha,should,istanbul
    • 调试日志打印debug模块
  • Express

    • 1.1 Express概览篇
    • 1.2 Express
  • Koa2

    • 1.0 koa2概览篇
    • 1.1 快速开始
    • 1.2 async await使用
    • 1.3 koa2简析结构
    • 1.4 koa中间件开发与使用
    • 10.1 单元测试
    • 11.1 开发debug
    • 12.1 快速启动
    • 12.2 框架设计
    • 12.3 分层操作
    • 12.4 数据库设计
    • 12.5 路由设计
    • 12.6 webpack4环境搭建
    • 12.7 使用react
    • 12.8 登录注册功能实现
    • 12.9 session登录态判断处理
    • 13.1 import export使用
    • 2.1 原生koa2实现路由
    • 2.2 koa router中间
    • 3.1 GET请求数据获取
    • 3.2 POST请求数据获取
    • 3.3 koa bodyparser中间件
    • 4.1 原生koa2实现静态资源服务器
    • 4.2 koa static中间件
    • 5.1 koa2使用cookie
    • 5.2 koa2实现session
    • 6.1 koa2加载模板引擎
    • 6.2 ejs模板引擎
    • 7.1 busboy模块
    • 7.2 上传文件简单实现
    • 7.3 异步上传图片实现
    • 8.1 mysql模块
    • 8.2 async await封装使用mysql
    • 8.3 项目建表初始化
    • 9.1 原生koa2实现JSONP
    • 9.2 koa jsonp中间件
  • 其他

    • 操作数据库
    • Session 与 Token
    • Cookie、Session、Token、JWT
    • Socket
完整面试题地址:
作者:程序员poetry
扫码关注作者公众号:「前端进阶之旅」 每天分享技术干货
前端进阶之旅公众号二维码

URL查询字符串 querystring|Nodejs专题系列

# URL查询字符串 querystring

30 秒速记

  • querystring 是 Node.js 老模块,官方标了 legacy;新代码用全局的 URLSearchParams
  • 重复键:querystring.parse 给数组,URLSearchParams 用 get 拿第一个、getAll 拿全部
  • 值永远是字符串,page=2 拿到的是 '2',数字布尔要自己转
  • 空格编码不同:querystring 是 %20,URLSearchParams 是 +
  • querystring.parse 默认最多解析 1000 个键(maxKeys),防恶意超长参数

查询字符串就是 ? 后面那串 a=1&b=2,Node.js 里老办法是 querystring 模块,新办法是 URLSearchParams。 两者都能解析和拼接,但细节不同:重复键 querystring 直接给数组,URLSearchParams 要用 getAll;空格一个编成 %20、一个编成 +。不管用哪个,拿到的值都是字符串,page=2 拿到 '2',直接相加就变成字符串拼接。所以我在接口入口一定会配一层 schema 校验,把类型、默认值、是否允许多值都定下来。

理解「URL查询字符串 querystring」时,要先明确输入、运行阶段和可观察输出。这里的交互实验会分别执行正常路径与失败路径,并把 Node.js 的关键状态变化和同屏代码对应起来;不能只记命令名称。

工程中还要验证退出码、资源清理和异常输入。属于 buffer 场景的配置应保持最小可复现,并在开发环境与 CI 中使用相同命令复跑,避免把平台差异或隐式默认值带到线上。

面试官追问

追问 1?tag=js&tag=node,querystring.parse 和 URLSearchParams 各拿到什么?
参考回答

querystring.parse 得到 { tag: ['js', 'node'] };URLSearchParams 的 get('tag') 是 'js',getAll('tag') 是两个都有。要是用 Object.fromEntries(params) 转对象,只剩最后一个 'node'。

追问 2筛选接口有时收到字符串、有时收到数组,代码一会儿正常一会儿报错,怎么治?
参考回答

这是重复键导致的类型不稳定。入口统一规整:[].concat(q.tag ?? []) 永远转数组,或者用 getAll。更好的是用 zod 这类 schema 明确每个字段是单值还是多值。

追问 3?debug=false,代码里 if (q.debug) 却进了分支,为什么?
参考回答

'false' 是非空字符串,是真值。查询参数要显式转换,比如 q.debug === 'true',别依赖 JS 的真假值判断。

追问 4有人传了几万个参数的超长查询串,服务会不会被拖垮?
参考回答

querystring.parse 默认 maxKeys 是 1000,超出部分直接丢掉,能挡一部分。但更该在网关或框架层限制 URL 总长度,Node.js 本身对请求头总大小默认也有约 16KB 的上限。

# 模块概述

30 秒速记

  • querystring 四个方法:parse、stringify、escape、unescape,日常只用前两个
  • parse:字符串 → 对象;stringify:对象 → 字符串
  • parse 返回的对象没有原型,obj.hasOwnProperty 会报错
  • 不做嵌套:a[b]=1 解析出的键就是 'a[b]',要嵌套用 qs 库
  • decode / encode 是 parse / stringify 的别名

querystring 是 Node.js 处理查询参数的老模块,核心就两个方法:parse 把字符串解析成对象,stringify 反过来。 用起来很简单,但有两个细节常被问。一是 parse 返回的对象是用 Object.create(null) 造的,没有原型,obj.hasOwnProperty('a') 直接报错,要用 Object.hasOwn(obj, 'a')。二是它不支持嵌套,user[name]=tom 解析出来键名就是 'user[name]',Express 能解析嵌套是因为默认用了 qs 库。

在nodejs中,提供了querystring这个模块,用来做url查询参数的解析,使用非常简单。

模块总共有四个方法,绝大部分时,我们只会用到 .parse()、 **.stringify()**两个方法。剩余的方法,感兴趣的同学可自行查看文档。

  • .parse():对url查询参数(字符串)进行解析,生成易于分析的json格式。
  • .stringif():跟**.parse()**相反,用于拼接查询查询。
querystring.parse(str[, sep[, eq[, options]]])
querystring.stringify(obj[, sep[, eq[, options]]])
@前端进阶之旅: 代码已经复制到剪贴板

面试官追问

追问 1querystring.parse(str).hasOwnProperty('a') 报 is not a function,为什么?
参考回答

返回的对象没有原型,自然没有 hasOwnProperty。改成 Object.hasOwn(obj, 'a') 或 'a' in obj。这样设计是为了防止 ?__proto__=x 这类参数污染原型。

追问 2前端传 user[name]=tom&user[age]=18,querystring 能解析成嵌套对象吗?
参考回答

不能,得到的是 { 'user[name]': 'tom', 'user[age]': '18' }。要嵌套就用 qs,不过嵌套查询串本身就容易引发原型污染和类型混乱,复杂结构我更倾向放到 POST 的 JSON 里。

追问 3querystring.parse('a=1+2') 拿到的 a 是什么?
参考回答

'1 2',+ 会被当成空格解码。如果值里真要一个加号,传的时候得编码成 %2B。

追问 4querystring 和 URLSearchParams,新项目选哪个?
参考回答

选 URLSearchParams,浏览器和 Node.js 都是全局可用,前后端一套写法。querystring 唯一的优势是能自定义分隔符,对接非标准格式时才用得上。

# 查询参数解析:querystring.parse()

30 秒速记

  • querystring.parse(str, sep = '&', eq = '=', options)
  • 'nick=casper&age=24' → { nick: 'casper', age: '24' },age 是字符串
  • sep / eq 换分隔符:parse('name-chyingp|country-cn', '|', '-') 也能解析
  • options.maxKeys 默认 1000,传 0 不限;options.decodeURIComponent 可换解码函数
  • 边界:a → { a: '' },a= → { a: '' },重复键 → 数组

querystring.parse 把 a=1&b=2 这种字符串拆成对象,默认用 & 分参数、= 分键值。 第二三个参数可以换掉这两个符号,适合对接 name-chyingp|country-cn 这种自定义格式,不用自己写两层 split。第四个参数用得少,主要是 maxKeys,默认只解析前 1000 个键。要记住的是它不做类型推断,age=24 拿到的是字符串 '24',空值和没写等号都是空字符串,重复键会变成数组。

参数:querystring.parse(str[, sep[, eq[, options]]])

第四个参数几乎不会用到,直接不讨论. 第二个, 第三个其实也很少用到,但某些时候还是可以用一下。直接看例子

var querystring = require('querystring');
var str = 'nick=casper&age=24';
var obj = querystring.parse(str);
console.log(JSON.stringify(obj, null, 4));
@前端进阶之旅: 代码已经复制到剪贴板

输出如下

{
    "nick": "casper",
    "age": "24"
}
@前端进阶之旅: 代码已经复制到剪贴板

再来看下sep、eq有什么作用。相当于可以替换&、=为自定义字符,对于下面的场景来说还是挺省事的。

var str1 = 'nick=casper&age=24&extra=name-chyingp|country-cn';
var obj1 = querystring.parse(str1);
var obj2 = querystring.parse(obj1.extra, '|', '-');
console.log(JSON.stringify(obj2, null, 4));
@前端进阶之旅: 代码已经复制到剪贴板

输出如下

{
    "name": "chyingp",
    "country": "cn"
}
@前端进阶之旅: 代码已经复制到剪贴板

面试官追问

追问 1age=24 解析出来直接 obj.age + 1,结果是 '241',怎么改?
参考回答

parse 只拆字符串不转类型,要显式 Number(obj.age),并且判断 Number.isNaN。入口统一做 schema 校验是更省心的办法。

追问 2外层是标准查询串,里面 extra=name-a|country-cn 又是一层自定义格式,怎么解析?
参考回答

两步走:先 const outer = querystring.parse(str),再 querystring.parse(outer.extra, '|', '-')。第二步前要判断 extra 是字符串,如果 extra 出现两次,它会是数组,直接传进去会出错。

追问 3parse('name-a|country-cn', '-', '|') 结果不对,问题出在哪?
参考回答

sep 和 eq 传反了,第二个参数是参数之间的分隔符,第三个才是键值之间的。正确写法是 parse(str, '|', '-')。

追问 4值里本身就带 |,用 | 当分隔符会怎样?
参考回答

会被误拆成多个参数。要么约定值里的 | 先编码,要么换一个不会出现在值里的分隔符。自定义格式最怕的就是没有转义规则。

追问 5?a&b= 解析出来是什么?
参考回答

{ a: '', b: '' },没写等号和等号后为空,结果一样都是空字符串。如果业务要区分「没传」和「传了空」,querystring 做不到,只能看原始字符串。

# 查询参数拼接:querystring.stringify()

← 5.0 网络地址解析 url6.1 流操作 stream →

fe