分类处理
JS 基本数据类型 null undefined number string boolean(ES5) Bigint Symbol(ES6)
JS 复杂数据类型 object date array function regExp...
基本上都是转字符串, 字符串本身再转, Bigint不能转会爆类型错误, Symbol, function转undefined(在数组里会被转成null,在对象内会被忽略), regExp转{}, date的话通过date.toJSON()再转字符串
代码实现
主函数
// JSON.Stringify
const jsonStringify = function(data) {
return handleType(data) === 'object' ? handleJsonStringifyIsObject(data) : handleJsonStringifyNotObject(data);
}
判断类型
const handleType = function(target) {
return typeof target;
}
处理typeof!=='object'
// 情况1 : 处理typeof检测的非对象 PS NaN/Infinity类型为number // null undefined boolean string number BigInt
const handleJsonStringifyNotObject = function(data) {
if(Number.isNaN(data) || data === Infinity) return "null";
if(handleType(data) === 'undefined' || handleType(data) === 'symbol') return undefined;
if(handleType(data) === 'string') return `'${data}'`
if(handleType(data) === 'boolean' || handleType(data) === 'number') return `${data}`
if(data instanceof Function) return undefined;
if(handleType(data) === 'bigint') throw new TypeError('Do not know how to serialize a BigInt');
return data;
}
处理typeof==='object'
// 情况2 : 处理对象类型 大致为 null/regExp/array/object PS:历史原因null为object 数组和对象需要遍历执行
const handleJsonStringifyIsObject = function(data) {
if(data === null) return 'null';
if(data.toJSON && typeof data.toJSON === 'function') return jsonStringify(data.toJSON()); // 处理 Date 的序列化
if(data instanceof RegExp) return "{}";
if(data instanceof Array) return handleJsonStringifyArray(data);
return handleJsonStringifyObject(data);
}
遍历数组
// 情况2 下的情况小1: 遍历对象进行序列化
const handleJsonStringifyObject = function(data) {
let result = [];
Object.keys(data).forEach((item, index)=>{
if(handleType(item) === 'symbol' || handleType(data[item]) === 'symbol' || data[item] === undefined || handleType(data[item]) === 'function') {
}
else
result.push(`"${item}":${jsonStringify(data[item])}`);
})
return `{${result}}`.replace(/'/g, '"');
}
遍历对象
// 情况2 下的情况小2: 遍历数组进行序列化
const handleJsonStringifyArray = function(data) {
let result = [];
data.forEach((item, index)=>{
if(item === 'undefined' || handleType(item) === 'function' || handleType(item) === 'symbol' || item === undefined) result[index] = "null";
else result[index] = jsonStringify(item);
})
return `[${result}]`.replace(/'/g, '"');
}
完整代码
const handleType = function(target) {
return typeof target;
}
// 情况2 下的情况小2: 遍历数组进行序列化
const handleJsonStringifyArray = function(data) {
let result = [];
data.forEach((item, index)=>{
if(item === 'undefined' || handleType(item) === 'function' || handleType(item) === 'symbol' || item === undefined) result[index] = "null";
else result[index] = jsonStringify(item);
})
return `[${result}]`.replace(/'/g, '"');
}
// 情况2 下的情况小1: 遍历对象进行序列化
const handleJsonStringifyObject = function(data) {
let result = [];
Object.keys(data).forEach((item, index)=>{
if(handleType(item) === 'symbol' || handleType(data[item]) === 'symbol' || data[item] === undefined || handleType(data[item]) === 'function') {
}
else
result.push(`"${item}":${jsonStringify(data[item])}`);
})
return `{${result}}`.replace(/'/g, '"');
}
// 情况2 : 处理对象类型 大致为 null/regExp/array/object PS:历史原因null为object 数组和对象需要遍历执行
const handleJsonStringifyIsObject = function(data) {
if(data === null) return 'null';
if(data.toJSON && typeof data.toJSON === 'function') return jsonStringify(data.toJSON()); // 处理 Date 的序列化
if(data instanceof RegExp) return "{}";
if(data instanceof Array) return handleJsonStringifyArray(data);
return handleJsonStringifyObject(data);
}
// 情况1 : 处理typeof检测的非对象 PS NaN/Infinity类型为number // null undefined boolean string number BigInt
const handleJsonStringifyNotObject = function(data) {
if(Number.isNaN(data) || data === Infinity) return "null";
if(handleType(data) === 'undefined' || handleType(data) === 'symbol') return undefined;
if(handleType(data) === 'string') return `'${data}'`
if(handleType(data) === 'boolean' || handleType(data) === 'number') return `${data}`
if(data instanceof Function) return undefined;
if(handleType(data) === 'bigint') throw new TypeError('Do not know how to serialize a BigInt');
return data;
}
// JSON.Stringify
const jsonStringify = function(data) {
return handleType(data) === 'object' ? handleJsonStringifyIsObject(data) : handleJsonStringifyNotObject(data);
}
// TODO Test
let obj = {
name: 'sina', // string
age: 21, // number
love: Infinity, // infinity
ability: NaN, //NaN
brith: new Date(), // date
address: { // object
'country': 'CN',
'city': 'NC'
},
sex: true,
// only: Symbol(1),
regexp: new RegExp(/\s+/g),
// 以下都未处理
function: function add(a,b) {return a+b;},
undefine: undefined,
symbol: Symbol(1),
}
// function->undefined
function add(a,b) {return a+b;};
let arr = [add, Symbol(1), undefined];
// array->array
console.log(jsonStringify(arr));
console.log(JSON.stringify(arr));
// function->undefined
console.log(jsonStringify(add));
console.log(JSON.stringify(add));
// boolean->'boolean'
console.log(jsonStringify(true));
console.log(JSON.stringify(true));
// number->'number'
console.log(jsonStringify(12));
console.log(JSON.stringify(12));
// null->'null'
console.log(jsonStringify(null));
console.log(JSON.stringify(null));
// undefined->undefined
console.log(jsonStringify(undefined));
console.log(JSON.stringify(undefined));
// string->"'string'"
console.log(jsonStringify('undefined'));
console.log(JSON.stringify('undefined'));
// symbol->undefined
console.log(jsonStringify(Symbol(1)));
console.log(JSON.stringify(Symbol(1)));
// array->'array'
console.log(jsonStringify([1,2,3]));
console.log(JSON.stringify([1,2,3]));
// date->'array'
console.log(jsonStringify(new Date()));
console.log(JSON.stringify(new Date()));
// obj->"'obj'"
console.log(jsonStringify(obj));
console.log(JSON.stringify(obj));
// regExp->'{}'
console.log(jsonStringify(new RegExp()));
console.log(JSON.stringify(new RegExp()));
// Bigint->'Uncaught TypeError: Do not know how to serialize a BigInt '
console.log(jsonStringify(BigInt(1)));
console.log(JSON.stringify(BigInt(1)));
总结
基本上都是转字符串, 字符串本身再转, Bigint不能转会爆类型错误, Symbol, function转undefined(在数组里会被转成null,在对象内会被忽略), regExp转{}, date的话通过date.toJSON()再转字符串