首先看一下MDN上对JSON.stringify()的解释
JSON.stringify() 方法将一个 JavaScript 对象或值转换为 JSON 字符串,如果指定了一个 replacer 函数,则可以选择性地替换值,或者指定的 replacer 是数组,则可选择性地仅包含数组指定的属性
语法:JSON.stringify(value[, replacer [, space]])
value :要转换的值
replacer :如果该参数是一个函数,则在序列化过程中,被序列化的值的每个属性都会经过该函数的转 换和处理;如果该参数是一个数组,则只有包含在这个数组中的属性名才会被序列化到最终的 JSON 字符串中;如果该参数为 null 或者未提供,则对象所有的属性都会被序列化
space : 指定缩进用的空白字符串
JSON.stringify()就是将js对象或值转换成JSON字符串,比如
console.log(JSON.stringify(22)) //"22"
console.log(JSON.stringify('str')) //"str"
console.log(JSON.stringify(true)) //"true"
console.log(JSON.stringify(undefined)) //undefined
console.log(JSON.stringify(null)) //null
console.log(JSON.stringify(Symbol('foo'))) //undefined
console.log(JSON.stringify(new Date())) //"2021-05-12T10:13:37.393Z"
console.log(JSON.stringify(/a/g)) //{}
console.log(JSON.stringify({a:2,f:function(){},c:true,[Symbol('sym')]:2})) //{"a":2,"c":true}
let obj2 = {}
Object.defineProperty(obj2,'key',{
value:2,
enumerable:false
})
console.log(obj2) //{key:2}
console.log(JSON.stringify(obj2)) //{}
如上所示,有些类型在转换的过程中被转换为了null 或者是 undefined 甚至是一个对象中的属性直接被忽略,对象里面的不可枚举属性转换完之后也没了
整理了一下表格,可以来看一下json.stringify()在转换过程中的问题,具体的可以看一下MDN,我们可以根据表格的输入输出来手写一下json.stringify()这个方法
function isStringify(data){
let type = typeof data
// 判断基本数据类型
if(type !== 'object'){
// 如果是数字的话 返回
let result = data
// 如果是NAN或者是infinity
if(Number.isNaN(data)||data == Infinity){
result = "null"
}else if(type == 'function' || type =='undefined'||type == 'symbol' ){
//如果是function undefined 或者是symbol
result = 'undefined'
}else if(type =='string'){
result = '"'+data+'"'
}
//转换为字符串
return String(result)
}else if(type == 'object'){
// typeof null也是object
if(data == null){
return "null"
}else if(data.toJSON && typeof data.toJSON == 'function'){
// 如果有这个方法 会直接调用这个方法
return isStringify(data.toJSON())
}else if(data instanceof Array){
// 如果是数组
let result = []
// 遍历数组的每一项挨个处理
data.forEach((item,index)=>{
// 如果是undefined function symbol
if(typeof item == 'undefined' || typeof item == 'function' ||typeof item == 'symbol'){
result[index] = "null"
}else{
result[index] = isStringify(item)
}
})
result = "[" + result + "]" //字符串拼接 将数组转换为字符串了
return result.replace(/'/g,'"')
}else{
// 处理普通的对象
let result = []
Object.keys(data).forEach((item,index)=>{
if(typeof item !== 'symbol'){
//如果键名是symbol 自动忽略
if(typeof data[item] !== 'undefined' && typeof data[item] !== 'function' && typeof data[item] !== 'symbol'){
// 如果键值是undefined function symbol 自动忽略
// 否则的话拼接成字符串key:value的方式
result.push('"'+item+'"'+":"+isStringify(data[item]))
}
}
})
// 拼接成字符串然后返回
return "{"+result+"}".replace(/'/g,'"')
}
}
}
测试:
let arr = [1,'str',Symbol('foo'),true,null,undefined,function(){}]
console.log(JSON.stringify(arr) == isStringify(arr)) //true
let obj = {
date:new Date(),
[Symbol('symbol')]:22,
reg:new RegExp('a'),
fun(){
console.log(11)
},
b:undefined,
s:Symbol('sym2')
}
console.log(JSON.stringify(obj) == isStringify(obj)) //true
JSON.stringify()还可以深拷贝,但是从JSON.stringify()转换为JSON字符串时候的规范来看,深拷贝中可能会有问题,还是要根据需求来使用…