# 重学JSON.stringify

# 语法

JSON.stringify()方法将一个 JavaScript 对象或值转换为 JSON 字符串,如果指定了一个 replacer 函数,则可以选择性地替换值,或者指定的 replacer 是数组,则可选择性地仅包含数组指定的属性。

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

value: 将要序列化成 一个 JSON 字符串的值。 replacer(可选):如果该参数是一个函数,则在序列化过程中,被序列化的值的每个属性都会经过该函数的转换和处理;如果该参数是一个数组,则只有包含在这个数组中的属性名才会被序列化到最终的 JSON 字符串中;如果该参数为 null 或者未提供,则对象所有的属性都会被序列化。 space(可选):指定缩进用的空白字符串,用于美化输出(pretty-print);如果参数是个数字,它代表有多少的空格;上限为10。该值若小于1,则意味着没有空格;如果该参数为字符串(当字符串长度超过10个字母,取其前10个字母),该字符串将被作为空格;如果该参数没有提供(或者为 null),将没有空格。

返回值:一个表示给定值的JSON字符串。

异常:

  • 当在循环引用时会抛出异常TypeError ("cyclic object value")(循环对象值)
  • 当尝试去转换 BigInt 类型的值会抛出TypeError ("BigInt value can't be serialized in JSON")(BigInt值不能JSON序列化)

# 特性

# 特性一

  1. undefined、任意的函数以及symbol值,出现在非数组对象的属性值中时在序列化过程中会被忽略
  2. undefined、任意的函数以及symbol值出现在数组中时会被转换成 null
  3. undefined、任意的函数以及symbol值被单独转换时,会返回 undefined

# 特性二

布尔值、数字、字符串的包装对象在序列化过程中会自动转换成对应的原始值。

console.log(JSON.stringify([new Number(1), new String("前端"), new Boolean(false)]))

// [1,"前端",false]
1
2
3

# 特性三

所有以symbol为属性键的属性都会被完全忽略掉,即便 replacer 参数中强制指定包含了它们。

console.log(JSON.stringify({
  [ Symbol('前端') ]: '前端',
}, (key, value) => {
  if (typeof key === 'symbol') {
    return value
  }
}))

 // undefined
1
2
3
4
5
6
7
8
9

# 特性四

NaNInfinity 格式的数值及 null 都会被当做 null

console.log(JSON.stringify({num1: NaN, num2: Infinity, num3: null}))

// {"num1":null,"num2":null,"num3":null}
1
2
3

# 特性五

转换值如果有 toJSON() 方法,该方法定义什么值将被序列化。

console.log(JSON.stringify({
  name: '前端',
  toJSON () {
    return 'JSON.stringify'
  }
}))

// "JSON.stringify"
1
2
3
4
5
6
7
8

# 特性六

Date 日期调用了 toJSON() 将其转换为了 string 字符串(同Date.toISOString()),因此会被当做字符串处理。

console.log(JSON.stringify(new Date()))

// "2021-10-27T05:55:58.208Z"
1
2
3

# 特性七

对包含循环引用的对象(对象之间相互引用,形成无限循环)执行此方法,会抛出错误。该特性对应上述语法小节的异常里。

# 特性八

其他类型的对象,包括Map/Set/WeakMap/WeakSet,仅会序列化可枚举的属性。

console.log(JSON.stringify(Object.defineProperties({}, {
  name: {
    value: '前端',
    enumerable: true
  },
  sex: {
    value: 'boy',
    enumerable: false // 不可枚举
  },
})))

// {"name":"前端"}
1
2
3
4
5
6
7
8
9
10
11
12

# 特性九

当尝试去转换 BigInt 类型的值会抛出错误。

console.log(JSON.stringify(BigInt(1)))

// TypeError: Do not know how to serialize a BigInt
1
2
3

# 总结

本文介绍了JSON.stringify的语法,以及该方法的九大特性。当我们使用JSON.stringify的时候,一定要注意特殊情况,防止出现属性和值丢失。