返回 剖析
手动实现
JSON.stringify() 揭秘:亲自动手打造 JSON 序列化引擎
前端
2023-12-17 02:06:43
在 JavaScript 的生态圈中,JSON.stringify()
方法扮演着至关重要的角色,负责将 JavaScript 对象优雅地转换为 JSON 字符串。然而,这个看似简单的过程背后隐藏着令人着迷的算法和技术细节。在这篇深入的文章中,我们将踏上一段探索之旅,一步一步剖析 JSON.stringify()
方法的内在原理,亲自动手打造一个属于自己的 JSON 序列化引擎。
构建 JSON 序列化引擎的奥秘
JSON.stringify()
方法的工作原理建立在两个核心概念之上:
- 递归遍历: 方法通过深度优先遍历 JavaScript 对象,逐层解析其键值对。
- 值类型处理: 不同类型的值(字符串、数字、布尔值等)需要遵循特定的规则进行序列化。
剖析 JSON.stringify()
的算法
1. 入口点:
JSON.stringify(obj, replacer, space)
obj
:要序列化的 JavaScript 对象。replacer
(可选):用于自定义序列化的函数。space
(可选):用于美化输出 JSON 字符串的空格数。
2. 值类型处理:
- 字符串: 使用双引号包裹并转义特殊字符。
- 数字、布尔值、null: 直接输出值本身。
- 数组: 使用方括号包裹并递归调用
JSON.stringify()
。 - 对象: 使用大括号包裹并递归调用
JSON.stringify()
,遵循键值对的顺序。 - 未定义、函数、Symbol: 转换为
null
。
3. 循环引用处理:
为防止无限递归,在遍历过程中维护一个包含已序列化的对象引用的数组。如果遇到一个循环引用,则替换为 null
。
4. 字符串化过程:
- 将所有值序列化为字符串。
- 对于对象,将键和值按顺序连接为字符串。
- 对于数组,将元素连接为字符串,并用逗号分隔。
- 根据
space
参数,添加空格以美化输出。
手动实现 JSON.stringify()
1. 初始化:
function stringify(obj) {
let output = '';
const seen = [];
return serialize(obj, seen, output);
}
2. 递归序列化函数:
function serialize(obj, seen, output) {
// 处理值类型
if (typeof obj === 'string') {
// 字符串转义
return '"' + escape(obj) + '"';
} else if (typeof obj === 'number' || typeof obj === 'boolean' || obj === null) {
// 直接输出值
return obj.toString();
} else if (Array.isArray(obj)) {
// 处理数组
return '[' + obj.map(val => serialize(val, seen, output)).join(',') + ']';
} else if (typeof obj === 'object') {
// 处理对象
if (seen.includes(obj)) {
// 循环引用
return 'null';
}
seen.push(obj);
const keys = Object.keys(obj);
return '{' + keys.map(key => serialize(key, seen, output) + ':' + serialize(obj[key], seen, output)).join(',') + '}';
} else {
// 未定义、函数、Symbol
return 'null';
}
}
3. 字符串转义:
function escape(str) {
return str.replace(/[\u0000-\u001f\"\\\//g, char => {
switch (char) {
case '\b': return '\\b';
case '\f': return '\\f';
case '\n': return '\\n';
case '\r': return '\\r';
case '\t': return '\\t';
case '\'': return '\\\'';
case '"': return '\\"';
case '\\': return '\\\\';
case '/': return '\\/';
default: return '\\u' + char.charCodeAt(0).toString(16).padStart(4, '0');
}
});
}
通过遵循这些步骤,你可以亲手构建一个功能完备的 JSON 序列化引擎,它可以将任何 JavaScript 对象转换为一个有效的 JSON 字符串。