igCircle Blog

JSON方法的妙用

2021年9月18日

7分钟阅读

4 次浏览

0 条评论

前端三大件

标签

JSON

JSON 方法的妙用 1 基本用法--序列化 `js let json1 = { name: 'Tom', brother: ['jerry', 'jack'], age: 3, gender: undefined, say: '', } let jsonString = JSON.stringify(json1) //默认情况下,JSON.stringify()会输出不包含空格或...

JSON 方法的妙用

1 基本用法--序列化

js
1let json1 = {
2 name: 'Tom',
3 brother: ['jerry', 'jack'],
4 age: 3,
5 gender: undefined,
6 say: '',
7}
8
9let jsonString = JSON.stringify(json1)
10//默认情况下,JSON.stringify()会输出不包含空格或缩进的JSON字符串
11//值为undefined的任何属性也会被跳过 空串不会被跳过
12console.log(jsonString) //{"name":"Tom","brother":["jerry","jack"],"age":3,"say":""}
13console.log(typeof jsonString) //string

2 进阶使用-- 过滤器

在 JSON.stringify()方法一共能接受 3 个参数,其中两个可选的参数(分别是第二、第三个参数)。

这两个可选参数可以用于指定其他序列化 JavaScript 对象的方式。

第二个参数是过滤器,可以是数组或函数;

第三个参数是用于缩进结果 JSON 字符串的选项。

单独或组合使用这些参数可以更好地控制 JSON 序列化。

js
1let json1 = {
2 name: 'Tom',
3 brother: ['jerry', 'jack'],
4 age: 3,
5 gender: 'male',
6}
7
8//第二个参数为数组的情况 结果JSON字符串中只会包含数组里面指定的属性:
9let jsonString = JSON.stringify(json1, ['gender', 'age'])
10console.log(jsonString) //{"gender":"male","age":3}
11
12//第二个参数为函数的情况
13const students = [
14 {
15  name: 'james',
16  score: 100,
17 },
18 {
19  name: 'jordon',
20  score: 60,
21 },
22 {
23  name: 'kobe',
24  score: 90,
25 },
26]
27
28//值得注意的是,如果stringify的第二个参数为函数那么它的返回值如果是undefined,
29//那么对应的属性不会被序列化,如果返回其他的值,那么用返回的值替代原来的值进行序列化。
30function replacer(key, value) {
31 if (key === 'score') {
32  if (value === 100) {
33   return 'S'
34  } else if (value >= 90) {
35   return 'A'
36  } else if (value >= 70) {
37   return 'B'
38  } else if (value >= 50) {
39   return 'C'
40  } else {
41   return 'E'
42  }
43 }
44 return value
45}
46
47//第三个参数控制缩进和空格。在这个参数是数值时,表示每一级缩进的空格数
48//4 表示缩进的空格
49let jsonString2 = JSON.stringify(students, replacer, 4)
50
51//,我们通过replacer将成绩从百分制替换为成绩等级。
52console.log(jsonString2)
53/*[
54    {
55        "name": "james",
56        "score": "S"
57    },
58    {
59        "name": "jordon",
60        "score": "C"
61    },
62    {
63        "name": "kobe",
64        "score": "A"
65    }
66]*/
67
68console.log(typeof jsonString2) //string

3 判断对象是否相等

这种方式存在着较大的局限性,对象如果调整了键的顺序,就会判断出错!不建议使用 可以只是作为一个了解

js
1let obj1 = {
2 a: 1,
3 b: 2,
4}
5
6let obj2 = {
7 a: 1,
8 b: 2,
9}
10
11let obj3 = {
12 a: 1,
13 b: 1,
14}
15
16let obj4 = {
17 b: 2,
18 a: 1,
19}
20console.log(JSON.stringify(obj1) === JSON.stringify(obj2)) //true
21console.log(JSON.stringify(obj1) === JSON.stringify(obj3)) //false
22
23//不过这种方式存在着较大的局限性,对象如果调整了键的顺序,就会判断出错!不建议使用
24console.log(JSON.stringify(obj1) === JSON.stringify(obj4)) //false  应该是true

4 判断对象中是否包含某个对象

js
1let data = [{ name: 'Tom' }, { name: 'jerry' }, { name: 'jack' }]
2
3let val = { name: 'jerry' }
4let val2 = { name: 'Rose' }
5
6console.log(JSON.stringify(data).indexOf(JSON.stringify(val)) !== -1) //true
7console.log(JSON.stringify(data).indexOf(JSON.stringify(val2)) !== -1) //false

5 深拷贝

原理是:利用 JSON.stringify 将对象转成 JSON 字符串,再用 JSON.parse 把字符串解析成对象,一去一来,新的对象产生了,新对象会开辟新的栈,实现深拷贝

缺点: 这种方法虽然可以实现数组或对象深拷贝,但不能处理函数和正则,因为这两者基于 JSON.stringify 和 JSON.pars 处理后,得到的正则就不再是正则(变为空对象),得到的函数就不再是函数(变为 null)了。因为不合法的对象 JSON 会自动进行处理

js
1let arr1 = [
2 1,
3 3,
4 {
5  username: ' kobe',
6 },
7]
8let arr2 = JSON.parse(JSON.stringify(arr1))
9arr2[2].username = 'duncan'
10console.log(arr1, arr2) //[ 1, 3, { username: ' kobe' } ] [ 1, 3, { username: 'duncan' } ]

6 toJSON 方法--自定义的 JSON 序列化

注意,箭头函数不能用来定义 toJSON()方法。主要原因是箭头函数的词法作用域是全局作用域(定义是所在的作用域),在这种情况下不合适。

js
1let json1 = {
2 name: 'Tom',
3 brother: ['jerry', 'jack'],
4 age: 3,
5 gender: undefined,
6 say: '',
7 //序列化时会基于这个方法返回适当的JSON表示
8 toJSON: function() {
9  return this.name
10 },
11}
12
13let jsonString = JSON.stringify(json1)
14console.log(jsonString) //"Tom"

7 实际使用例子

localStorage/sessionStorage 默认只能存储字符串,而实际开发中,我们往往需要存储对象类型,

那么此时我们需要在存储时利用 json.stringify()将对象转为字符串, 在取本地缓存时,使用 json.parse()转回对象即可

js
1// 存数据
2function setLocalStorage(key, val) {
3 window.localStorage.setItem(key, JSON.stringify(val))
4}
5// 取数据
6function getLocalStorage(key) {
7 let val = JSON.parse(window.localStorage.getItem(key))
8 return val
9}
10// 测试
11setLocalStorage('Test', ['tom', 'jerry'])
12console.log(getLocalStorage('Test')) //['tom','jerry']
13console.log(getLocalStorage('Test') instanceof Array) //true  数组也是对象

8 使用的注意事项

  1. 被转换值中有 NaN 和 Infinity 会被转换为 null
js
1let json1 = {
2 name: 'Tom',
3 brother: ['jerry', 'jack'],
4 age: Infinity,
5 say: NaN,
6}
7console.log(JSON.stringify(json1)) //{"name":"Tom","brother":["jerry","jack"],"age":null,"say":null}
  1. 被转换值中有 undefined、任意的函数以及 symbol 值

数组中 undefined、任意的函数以及 symbol 值在序列化的过程中会被转换成 null

js
1console.log(JSON.stringify([undefined, function() {}, Symbol('')])) //[null,null,null]

对象中:undefined、任意的函数以及 symbol 值在序列化的过程中会被忽略

js
1console.log(JSON.stringify({ x: undefined, y: function() {}, z: Symbol('') })) //{}
  1. 循环引用 得不到正确的结果 如果一个对象的属性值通过某种间接的方式指回该对象本身,那么就是一个循环引用。
js
1var bar = {
2 a: {
3  c: foo,
4 },
5}
6
7var foo = {
8 b: bar,
9}
10
11console.log(JSON.stringify(foo)) //{"b":{"a":{}}}
  1. 含有不可枚举的属性值时
js
1let personObj = Object.create(null, {
2 name: { value: 'Tom', enumerable: false },
3 year: { value: '1906', enumerable: true },
4})
5
6console.log(JSON.stringify(personObj)) // {"year":"1906"}

喜欢这篇文章吗?

加载中...

评论

0

登录后即可参与评论讨论

加载评论中...

相关文章

call bind apply的区别以及源码的手写

call方法的第一个参数也是this的指向,后面传入的是一个参数列表改变this指向后原函数会立即执行,且此方法只是临时改变this指向一次 当第一个参数为null、undefined的时候,默认指向window(在浏览器中) `js function fn(...args) { console.log(this的指向为${this}, args) } let obj = { ...

前端三大件
js手写

2025-08-06

2

0

目录