彻底弄懂JSON.stringify()

思考
以下代码执行结果是什么?
let list = [
  {
    name: 'leo',
    age: 18,
    like: undefined
  },
  {
    name: 'lion',
    age: 25,
    like: undefined
  }
]
console.log(JSON.stringify(list),'***JSON.stringify***')
带着疑问,一步步彻底了解 JSON.stringify()。(答案在文章末尾)
JSON.stringify() 的作用
JSON.stringify() 可以将 JavaScript 对象或值转换为 JSON 字符串(也称序列化)。
console.log(typeof {name:'leo',age:18})   // object
console.log(typeof JSON.stringify({name:'leo',age:18}))   // string
 
console.log(JSON.stringify({name:'leo',age:18}))   // '{"name":"leo","age":18}'
JSON.stringify() 有几点需要注意的地方,我们需要了解其使用规则,避免出现bug。
JSON.stringify() 的规则
如果目标对象存在 toJSON(),它负责定义哪些数据将被序列化
let obj = {
  name: 'leo',    
  age: 18,
  toJSON: function(){
    return '我是被序列化的部分'
  }
}
console.log(JSON.stringify(obj))   // '我是被序列化的部分'
Boolean、Number、String 对象在序列化过程中被转换为对应的原始值,符合传统的转换语义
let obj = {
  name: new String('leo'),
  age: new Number(18),
  like: new Boolean(true)
}
console.log(JSON.stringify(obj))   // '{"name":"leo","age":18,"like":true}'

undefined、Function 和 Symbol 不是有效的 JSON 值。
对象 (在对象中会被忽略)
let obj = {
  name: Symbol('leo'),
  age: undefined,
  like: function(){}
}
console.log(JSON.stringify(obj))   // {}
// 对象被序列化,undefined、Symbol、Function 忽略
数组 (在数组中会变为 null)
let arr = [Symbol('leo'), undefined, function(){}, 'lion']
console.log(JSON.stringify(arr))   // '[null,null,null,"lion"]'
// 数组被序列化,undefined、Symbol、Function 更改为 null
所有 Symbol - key 属性将被完全忽略
let obj = {
  [Symbol('name')]: 'leo',
  [Symbol('age')]: 18
}
console.log(obj)   // {Symbol(name): 'leo', Symbol(age): 18}  [[Prototype]]: Object
console.log(JSON.stringify(obj))   // {}
Date 的实例通过返回一个字符串来实现 toJSON()(与 date.toISOString() 相同)。因此,它们被视为字符串
console.log(new Date().toISOString())   // "2022-07-13T12:59:35.074Z"
console.log(JSON.stringify(new Date()))   // "2022-07-13T12:59:35.074Z"
数字 Infinity 和 NaN 以及 null 值都被认为是 null
let obj = {
  num1: Infinity,
  num2: NaN,
  num3: null,
  num4: 18
}
console.log(JSON.stringify(obj))   // '{"num1":null,"num2":null,"num3":null,"num4":18}'
所有其他 Object 实例(包括 Map、Set、WeakMap 和 WeakSet)仅序列化其可枚举的属性
let obj = {}
Object.defineProperties(obj,{
  name: {
    value: 'leo',
    enumerable: true
  },
  age: {
    value: 18,
    enumerable: false   // 不可枚举属性
  }
})
console.log(JSON.stringify(obj))   // '{"name":"leo"}'
找到循环引用时抛出 TypeError(“循环对象值”)异常
let obj = {
  name: 'leo',
  age: 18
}
obj.children = obj
console.log(JSON.stringify(obj))
完整语法

JSON.stringify(value[, replacer [, space]])

value(必选)
将要序列化成一个JSON 字符串的值。
replacer(可选)
可以是数组或函数。如果是数组,则只有包含在这个数组中的属性名才会被序列化。如果是函数,则把序列化后的每一个对象传进函数里进行处理。
  • 数组
let students = {
 name: "leo",
 age: 18,
 like: "sing"
}
let arr = ["name","age"]   // 序列化数组存在的属性,不存在的忽略
let obj = JSON.stringify(students, arr)
console.log(obj)
// '{"name":"leo","age":18}'
  • 函数
function replacer(key, value) {
  if (typeof value === "string") {   // 如果是字符串,则当成 undefined 序列化,即忽略
    return undefined
  }
  return value
}
 
let foo = {
  name: "leo",
  model: "box",
  age: 18,
  transport: "car",
  month: 7
};
let obj = JSON.stringify(foo, replacer)
console.log(obj)
// '{"age":18,"month":7}'
space(可选)
指定缩进用的空白字符串。如果省略的话,那么显示出来的值就没有分隔符。如果是一个数字,那么它就定义缩进几个字符,范围是 0-10(数字小于1,则默认为0,大于10,则默认为10)。如果是一些转义字符,比如“\t”,表示回车,那么它每行一个回车。如果仅仅是字符串,就在每行输出值的时候把这些字符串附加上去。
console.log(JSON.stringify({ a: 2 }, null, " "))
/* 输出结果:
'{
  "a": 2
}'
*/
 
console.log(JSON.stringify({ name: "leo", age: 18  }, null, '\t'))
/* 输出结果:
'{
    "name": "leo",
    "age": 18
}'
*/
 
let students = {
  name: "leo",
  age: 18,
  like: "run"
}
let arr = ["name","age"]
console.log(JSON.stringify(students, arr, "--"))
/* 输出结果:
'{
--"name": "leo",
--"age": 18
}'
*/
看完之后,上面的思考题,你知道执行结果是什么了吗???

'[{"name":"leo","age":18},{"name":"lion","age":25}]'

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,904评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,581评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,527评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,463评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,546评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,572评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,582评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,330评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,776评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,087评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,257评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,923评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,571评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,192评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,436评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,145评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352

推荐阅读更多精彩内容