2.JSON.stringify 的实现,要考虑 null、undefined
嵌套数组的环形遍历
题目
要实现一个简单版本的 JSON.stringify,需要处理不同类型的值,包括 null、undefined、对象、数组、字符串、数字等。
提示
DETAILS
- 基本数据类型处理:
- 对于 undefined 和函数,返回 undefined。
- 对于 null,返回字符串 "null"。
- 对于数字和布尔值,直接转换为字符串。
- 对于字符串,需要添加引号进行转换。
- 对象和数组处理:
- 使用递归来处理嵌套的对象和数组。
- 对于数组,遍历每个元素并使用 JSON.stringify 进行转换。
- 对于对象,遍历其属性,如果属性值是可序列化的,加入结果中。
- 处理循环引用:可以使用一个 Set 来追踪已经访问过的对象,以避免无限循环。
参考答案
DETAILS
<script>
function myStringify(value) {
// 用于跟踪已访问的对象,防止循环引用
const seen = new WeakSet();
function serialize(val) {
if (val === null) {
return "null"; // 处理 null
}
if (val === undefined) {
return undefined; // 处理 undefined
}
if (typeof val === "string") {
// 处理字符串,添加引号
return `"${val.replace(/"/g, '\\"')}"`;
}
if (typeof val === "number" || typeof val === "boolean") {
// 处理数字和布尔值
return String(val);
}
if (typeof val === "object") {
if (seen.has(val)) {
throw new TypeError("Converting circular structure to JSON"); // 处理循环引用
}
seen.add(val);
if (Array.isArray(val)) {
// 处理数组
const elements = val.map((item) => serialize(item));
console.log(elements,'elements--------')
return `[${elements.join(",")}]`;
} else {
// 处理对象
const props = Object.keys(val)
.map((key) => {
const serializedKey = serialize(key);
const serializedValue = serialize(val[key]);
return `${serializedKey}:${serializedValue}`;
})
.filter((prop) => prop !== undefined); // 过滤掉 undefined 的属性
return `{${props.join(",")}}`;
}
}
return undefined; // 处理函数类型
}
return serialize(value);
}
// 示例使用
const obj = {
name: "Alice",
age: null,
isStudent: true,
grades: [90, 80, null],
greet: undefined,
};
const arr = [1,2,3,4,5];
const num = 7;
const bol = true;
const str = 'nice';
console.log(myStringify(obj),'obj----------'); // 输出: {"name":"Alice","age:null","isStudent:true","grades":[90,80,null]}
console.log(myStringify(arr),'arr----------');
console.log(myStringify(num),'num----------');
console.log(myStringify(bol),'bol----------');
console.log(myStringify(str),'str----------');
</script>
注意事项
- 上述实现简单,不包括所有 JSON.stringify 的特性,比如处理日期、正则表达式等特殊对象。
- 如果遇到循环引用,将抛出错误。
- undefined 的属性会被忽略。
- 可以扩展此实现以支持更多的边界情况和数据类型。