手写 JSON.stringify
JSON.stringify 知识点(只有在熟悉了所有知识点才能开始手写)
1、作用:将对象转换成JSON字符串的格式,配合JSON.parse 可实现基础版的对象深拷贝 2、基本使用参数 语法:JSON.stringify(value[,replacer[,space]]
let oyobj1={
name:'Tim',
age:10,
friends:[1,2,3],
sex:'boy'
}
// 第一个参数:必须,需要序列化的对象
let objToString = JSON.stringify(myobj1);
console.log(objToString) // '{"name":"Tim","age":10,"friends":[1,2,3],"sex":"boy"}'
//第二个参数:需要对对象进行处理的函数
let objToString2 = JSON.stringify(myobj1,function(key,value){
if(typeof value === 'string') return undefined;
return value;
})
console.log(ObjToString2);//'{"age":10,"friends":[1,2,3]}'
// 第三个参数:对象之间的空格数
let objToString3 = JSON.stringify(myobj1,null,' ')
console.log(objToString3)
//'{\n "name": "Tim",\n "age": 10,\n "friends": [\n 1,\n 2,\n 3\n ],\n "sex": "boy"\n}'
3、JSON.stringify 对各种数据类型的处理
基础数据类型
输入类型 输出
string 字符串格式
number 字符串格式的数值
boolean "true"/"false"
null "null"
undefined/symbol "undefined"
NAN/+|-Infinity "null"
引用数据类型(属性类型)
输入类型 输出
function "undefined"
Date Date的toJSON 字符串
RegExp "{}"
(
数组中出现了
undefined\ null
Symbol \Function
)
普通对象 1、如果对象有ToJSON方法,
则序列化toJSON的返回值
值得注意的是:
1、如果对象属性值为undefiened/任意函数/symbol,则忽略
2、如果以Symbol 为属性键值的属性都被忽略
4、手写 JSON.stringify
function jsonStringify(data) {
let type = typeof data;
// 处理对基本数据类型的序列化
if (type !== "object") {
let result = data;
if (Number.isNaN(data) || data === Infinity) {
return "null";
}
if (type === "function" || type === "undefined" || type === "symbol") {
return undefined;
}
//字符串添加双引号是为了在对象递归调用时属性值添加引号
if (type === "string") {
return `"${data}"`;
}
return data;
} else {
// 对引用类型的处理
// null 虽然时基本数据类型,但 typeof null === 'object'
if (data === null) {
return "null";
}
//处理Date 的序列化
if (data.toJSON && typeof data.toJSON === "function") {
return jsonStringify(data.toJSON());
}
// 处理数组的每一项,每一项的类型可能不同,在数组中,undefined\function\symbol 类型
if (data instanceof Array) {
let result = [];
data.forEach((item, index) => {
let typeOfItem = typeof item;
if (
typeOfItem === "undefined" ||
typeOfItem === "function" ||
typeOfItem === "symbol"
) {
result[index] = "null";
} else {
result[index] = jsonStringify(item);
}
});
result = `[${result}]`;
return result.replace(/'/g, '"');
}
//处理普通对象,对于属性值为undefined/function/symbol 以及属性为symbol 的项直接忽略掉
let result = [];
Object.keys(data).forEach((item, index) => {
let typeOfprop = typeof item;
if (typeOfprop !== "symbol") {
let tyoeOfdata = typeof data[item];
if (
tyoeOfdata !== undefined &&
tyoeOfdata !== "function" &&
tyoeOfdata !== "symbol"
) {
result.push(`"${item}":${jsonStringify(data[item])}`);
}
}
});
return `{${result}}`.replace(/'/g, '"');
}
}
let obj2 = {
name: "myName",
age: 12,
hasMarried: false,
null: null,
undefined: undefined,
hobby: undefined,
getName() {
return this.name;
},
date: new Date(),
RegExp: new RegExp("a"),
array1: [1, 2, undefined, function () {}, 45],
obj3: {
name: "hello",
},
};
console.log(jsonStringify(obj2));
//{"name":"myName","age":12,"hasMarried":false,"null":null,"undefined":undefined,"hobby":undefined,"date":"2023-06-17T08:32:35.279Z","RegExp":{},"array1":[1,2,null,null,45],"obj3":{"name":"hello"}}
注意回答要点