🎯 一、为什么要掌握这两个方法的实现?
-
它们是前端数据处理最常用的接口之一
-
能力考察点:
- 对 JS 类型系统的理解(undefined、函数、Symbol)
- 递归遍历、数据序列化、字符串拼接能力
- 处理边界与异常(比如循环引用、非法 JSON 格式)
-
大厂面试喜欢问:"你能实现一个 JSON.stringify 吗?"
🧠 二、行为对比理解(标准 vs 简易实现)
特性 | JSON.stringify | JSON.parse |
---|---|---|
支持类型 | 数组、对象、数字、字符串、布尔、null | 字符串转回原对象 |
排除类型 | undefined 、function 、symbol (会被忽略) |
语法错误会 throw 异常 |
特性支持 | 支持递归嵌套、转义字符、循环引用报错 | 只能处理标准 JSON 字符串 |
✍️ 三、手写 JSON.stringify
简版实现
go
function jsonStringify(data) {
const type = typeof data;
if (data === null) return 'null';
if (type === 'number' || type === 'boolean') return String(data);
if (type === 'string') return `"${data.replace(/"/g, '\"')}"`;
if (type === 'undefined' || type === 'function' || type === 'symbol') return undefined;
if (Array.isArray(data)) {
const arr = data.map(item => {
const val = jsonStringify(item);
return val === undefined ? 'null' : val;
});
return `[${arr.join(',')}]`;
}
if (type === 'object') {
const keys = Object.keys(data);
const result = keys.reduce((acc, key) => {
const value = jsonStringify(data[key]);
if (value !== undefined) {
acc.push(`"${key}":${value}`);
}
return acc;
}, []);
return `{${result.join(',')}}`;
}
return undefined; // fallback
}
✅ 四、测试用例
sql
console.log(jsonStringify({ a: 1, b: 'x', c: undefined })); // {"a":1,"b":"x"}
console.log(jsonStringify([1, undefined, "hi"])); // [1,null,"hi"]
console.log(jsonStringify(null)); // null
❗ 五、注意事项(面试常问点)
问题 | 答案 |
---|---|
undefined 怎么处理? |
在数组中变 null ,在对象中被忽略 |
循环引用怎么办? | 要用 WeakSet 标记,避免无限递归(简版可不处理) |
如何处理转义字符? | 字符串中引号需转义,例如 " |
✍️ 六、手写 JSON.parse
简版实现
✅ 方法一:使用 eval
(⚠️ 不安全,仅限学习)
javascript
function jsonParse(str) {
return eval('(' + str + ')');
}
✅ 方法二:使用 Function
构造器(更安全)
javascript
function jsonParse(str) {
return new Function('return ' + str)();
}
⚠️ 两者都无法做格式校验,真实的
JSON.parse
会有严格语法校验与异常抛出机制。
✅ 七、测试用例
css
console.log(jsonParse('{"a":1,"b":[2,"x"]}')); // { a: 1, b: [2, "x"] }
📘 八、进阶加分建议
- ✅ 实现 replacer / space 参数(与官方
JSON.stringify(val, replacer, space)
一致) - ✅ 实现
toJSON()
自定义序列化规则支持 - ✅ 支持日期、正则(会转为字符串)、Symbol 忽略