手写实现JSON.stringfy()
面试考到了这个,之前从来没看过,写的焦头烂额。
查阅 MDN 发现 JSON.stringfy() 有很多注意的点,不是单纯把所有的东西都变成了字符串
**看一下MDN的描述**
有些乱,总结一下
规则 | 输入 | 输出 |
---|---|---|
1 | number | 字符串类型的数值 |
2 | NaN 和 Infinity | “null” |
3 | function | undefined |
4 | undefined | undefined |
5 | symbol | undefined |
6 | string | string(注意两边的双引号) |
7 | null | “null” |
8 | boolean | “true/false” |
9 | Date | Date的toJSON字符串值 |
10 | Array数组中出现了undefined、function 和 symbol | “null” |
11 | 普通object | 1、如果有 toJSON() 方法,那么序列化 toJSON() 的返回值; 2、如果属性值中出现了 undefined、函数、symbol,全部忽略; 3、所有以 symbol 为属性键的属性都会被完全忽略掉 |
12 | RegExp | “{}” |
13 | 循环引用 | 抛出错误 |
function myStringify(obj) {
let result = '';
var type = typeof obj;
if (type !== 'object' || obj === null) {
// 首先处理基本数据类型和function
if (type == 'number' && (Number.isNaN(obj) || !Number.isFinite(obj))) {
// 规则2:处理NaN和Infinite
result = 'null';
} else if (type == 'function' || type == 'undefined' || type == 'symbol') {
// 规则345:函数、undefined、symbol 被单独转换时,会返回 undefined,
result = 'undefined';
} else if (type == 'string') {
// 规则6:字符串,记得添加双引号,不能直接result = obj
result = `"${obj}"`;
} else {
// 规则78:处理null 和 boolean
result = obj;
}
// 转换为字符串
result = String(result);
} else {
if (obj.toJSON && typeof obj.toJSON == 'function') {
// 规则9:Date 有 toJSON() 方法,进行序列化。
result += myStringify(obj.toJSON());
} else if (obj instanceof Array) {
result = [];
obj.forEach((item, index) => {
let itemType = typeof item;
// 规则10:undefined、任意的函数以及 symbol 值,出现在数组中时,被转换成 null
if (
itemType == 'undefined' ||
itemType == 'function' ||
itemType == 'symbol'
) {
result[index] = 'null';
} else {
result[index] = myStringify(item);
}
});
result = `[${result}]`;
} else {
result = [];
Object.keys(obj).forEach((item, index) => {
// 规则11:所有以 symbol 为属性键的属性都会被完全忽略掉
// Object.keys返回包括对象自身的(不含继承的)所有可枚举属性(不含 Symbol 属性)的键名。
let valueType = typeof obj[item];
if (
valueType == 'undefined' ||
valueType == 'function' ||
valueType == 'symbol'
) {
// 规则11:普通object的undefined、任意的函数以及 symbol 值,在序列化过程中会被忽略
} else if (obj[item] == obj) {
// 规则13:对包含循环引用的对象执行此方法,会抛出错误。
throw TypeError('cyclic object value');
} else {
result.push(`"${item}":${myStringify(obj[item])}`);
}
});
// 规则12:这里其实处理了RegExp
// Obje.keys(RegExp类型)得出一个空数组,不会进入forEach循环,直接运行下行代码,变成一个空数组
result = `{${result}}`;
}
}
return result;
}
let obj = {
a: 1,
b: NaN,
c: Infinity,
d: undefined,
e: Symbol('123'),
f: 'hello',
g: null,
h: true,
i: new Date(),
j: [8, 'world', { aa: 9 }],
k: new RegExp(/dfs/),
l: function (a, b) {
return a + b;
},
};
let str = myStringify(obj);
let str1 = JSON.stringify(obj);
console.log(str);
console.log(str1);
用JSON.parse也可以解析回去~