在javascript里面,JSON.stringify是最常用的内置方法之一,这里尝试实现一个简易版的stringify
要实现stringify,首先要注意JSON.stringify的特点,为了简便,暂不考虑第二个replacer参数和第三个缩进参数,只考虑其它序列化特点:
- 忽略undefined:如果直接传一个undefiend给JSON.stringify,它会返回undefined;如果一个对象某个key的值是undefined,那么会忽略这个key,如果一个数组里面有undefined,那么忽略这些undefined的位置
- 忽略函数:特征跟undefined在数组,对象中类似,如果直接传函数给JSON.stringify,则也会返回undefined
- 忽略不可枚举属性
- 忽略原型属性 根据以上特点,使用递归加遍历的方法来实现:
function stringify(obj) {
if (obj === null) {
return 'null';
}
if (typeof obj === 'function') {
return undefined;
}
if (typeof obj === 'object') {
if (Array.isArray(obj)) {
const strList = [];
Object.values(obj).forEach(value => {
if (value !== undefined) {
strList.push(stringify(value));
}
});
const str = strList.join(',');
return '[' + str + ']'
} else {
const strList = []
Object.keys(obj).forEach(key => {
if (obj[key] !== undefined) {
strList.push('"' + key + '":' + stringify(obj[key]));
}
});
const str = strList.join(',');
return '{' + str + '}'
}
} else {
if (obj !== undefined) {
if (typeof obj === 'string') {
return '"' + obj + '"';
}
return String(obj);
}
return undefined;
}
}
在实现的过程中有几点需要注意:
- 必须使用全等(===)来判断undefined,==会将undefiend和null视为相等
- 使用===来判断null,因为typeof null值为'object',故需要单独判断
- 使用Array.isArray(ES6)来判断数组比使用instanceof Array更加严谨,因为Array不同document中的Array构造函数是被视作不同的,假设页面中有个iframe,产生的问题如下所示:
const frame = document.querySelector('frame');
const arr = [];
console.log(arr instanceof frame.contentWindow.Array) // false
console.log(frames[0].window.Array.isArray(arr)); // true