学透JSON.stringify

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

以下信息来自 MDN

语法

JSON.stringify(value[, replacer [, space]])
参数
  • value
    将要序列化成 一个 JSON 字符串的值。

  • replacer 可选

  1. 如果该参数是一个函数,则在序列化过程中,被序列化的值的每个属性都会经过该函数的转换和处理;
  2. 如果该参数是一个数组,则只有包含在这个数组中的属性名才会被序列化到最终的 JSON 字符串中;
  3. 如果该参数为 null 或者未提供,则对象所有的属性都会被序列化。
  • space 可选
  1. 指定缩进用的空白字符串,用于美化输出(pretty-print);
  2. 如果参数是个数字,它代表有多少的空格;上限为10。
  3. 该值若小于1,则意味着没有空格;
  4. 如果该参数为字符串(当字符串长度超过10个字母,取其前10个字母),该字符串将被作为空格;
  5. 如果该参数没有提供(或者为 null),将没有空格。
返回值
一个表示给定值的JSON字符串。
异常
  • 当在循环引用时会抛出异常TypeError (“cyclic object value”)(循环对象值)
  • 当尝试去转换 BigInt 类型的值会抛出TypeError (“BigInt value can’t be serialized in JSON”)(BigInt值不能JSON序列化).
基本使用
注意
  1. JSON.stringify可以转换对象或者值(平常用的更多的是转换对象)
  2. 可以指定replacer为函数选择性的地替换
  3. 也可以指定replacer为数组,可转换指定的属性

这里仅仅是MDN上关于JSON.stringify其中最基础的说明,咱们先打个码试试这几个特性

// 1. 转换对象
console.log(JSON.stringify({ name: '前端胖头鱼', sex: 'boy' })) // '{"name":"前端胖头鱼","sex":"boy"}'

// 2. 转换普通值
console.log(JSON.stringify('前端胖头鱼')) // "前端胖头鱼"
console.log(JSON.stringify(1)) // "1"
console.log(JSON.stringify(true)) // "true"
console.log(JSON.stringify(null)) // "null"

// 3. 指定replacer函数
console.log(JSON.stringify({ name: '前端胖头鱼', sex: 'boy', age: 100 }, (key, value) => {
  return typeof value === 'number' ? undefined : value
}))
// '{"name":"前端胖头鱼","sex":"boy"}'

// 4. 指定数组
console.log(JSON.stringify({ name: '前端胖头鱼', sex: 'boy', age: 100 }, [ 'name' ]))
// '{"name":"前端胖头鱼"}'

// 5. 指定space(美化输出)
console.log(JSON.stringify({ name: '前端胖头鱼', sex: 'boy', age: 100 }))
// '{"name":"前端胖头鱼","sex":"boy","age":100}'
console.log(JSON.stringify({ name: '前端胖头鱼', sex: 'boy', age: 100 }, null , 2))
/*
{
  "name": "前端胖头鱼",
  "sex": "boy",
  "age": 100
}
*/

9大特性要记住

以前仅仅是使用了这个方法,却没有详细了解他的转换规则,居然有9个之多。

特性一
  1. undefined任意的函数以及symbol值,出现在非数组对象的属性值中时在序列化过程中会被忽略
  2. undefined任意的函数以及symbol值出现在数组中时会被转换成 null。
  3. undefined任意的函数以及symbol值单独转换时,会返回 undefined
// 1. 对象中存在这三种值会被忽略
console.log(JSON.stringify({
  name: '前端胖头鱼',
  sex: 'boy',
  // 函数会被忽略
  showName () {
    console.log('前端胖头鱼')
  },
  // undefined会被忽略
  age: undefined,
  // Symbol会被忽略
  symbolName: Symbol('前端胖头鱼')
}))
// '{"name":"前端胖头鱼","sex":"boy"}'

// 2. 数组中存在着三种值会被转化为null
console.log(JSON.stringify([
  '前端胖头鱼',
  'boy',
  // 函数会被转化为null
  function showName () {
    console.log('前端胖头鱼')
  },
  //undefined会被转化为null
  undefined,
  //Symbol会被转化为null
  Symbol('前端胖头鱼')
]))
// '["前端胖头鱼","boy",null,null,null]'

// 3.单独转换会返回undefined
console.log(JSON.stringify(
  function showName () {
    console.log('前端胖头鱼')
  }
)) // undefined
console.log(JSON.stringify(undefined)) // undefined
console.log(JSON.stringify(Symbol('前端胖头鱼'))) // undefined
特性二

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

console.log(JSON.stringify([new Number(1), new String("前端胖头鱼"), new Boolean(false)]))
// '[1,"前端胖头鱼",false]'
特性三

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

console.log(JSON.stringify({
  name: Symbol('前端胖头鱼'),
}))
// '{}'
console.log(JSON.stringify({
  [ Symbol('前端胖头鱼') ]: '前端胖头鱼',
}, (key, value) => {
  if (typeof key === 'symbol') {
    return value
  }
}))
// undefined
特性四

NaN 和 Infinity 格式的数值及 null 都会被当做 null。

console.log(JSON.stringify({
  age: NaN,
  age2: Infinity,
  name: null
}))
// '{"age":null,"age2":null,"name":null}'
特性五

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

const toJSONObj = {
  name: '前端胖头鱼',
  toJSON () {
    return 'JSON.stringify'
  }
}

console.log(JSON.stringify(toJSONObj))
// "JSON.stringify"

特性六

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

const d = new Date()

console.log(d.toJSON()) // 2021-10-05T14:01:23.932Z
console.log(JSON.stringify(d)) // "2021-10-05T14:01:23.932Z"
特性七

对包含循环引用的对象(对象之间相互引用,形成无限循环)执行此方法,会抛出错误。

let cyclicObj = {
  name: '前端胖头鱼',
}

cyclicObj.obj = cyclicObj

console.log(JSON.stringify(cyclicObj))
// Converting circular structure to JSON

特性八

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

let enumerableObj = {}

Object.defineProperties(enumerableObj, {
  name: {
    value: '前端胖头鱼',
    enumerable: true
  },
  sex: {
    value: 'boy',
    enumerable: false
  },
})

console.log(JSON.stringify(enumerableObj))
// '{"name":"前端胖头鱼"}'

特性九

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

const alsoHuge = BigInt(9007199254740991)

console.log(JSON.stringify(alsoHuge))
// TypeError: Do not know how to serialize a BigInt
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值