学习了coderwhy的JavaScript高级语法视频课的笔记
如有错误或者不合适的地方,敬请见谅,欢迎指出和拓展,谢谢各位了
1. JSON的由来
- 在目前的开发中,JSON是一种非常重要的数据格式,它并不是编程语言,而是一种可以在服务器和客户端之间传输的数据格式。
- JSON的全称是JavaScript Object Notation(JavaScript对象符号):
- JSON是由Douglas Crockford构想和设计的一种轻量级资料交换格式,算是JavaScript的一个子集;
- 虽然JSON被提出来的时候是主要应用JavaScript中,但是目前已经独立于编程语言,可以在各个编程语言中使用;
- 很多编程语言都实现了将JSON转成对应模型的方式。
- 其他的传输格式:
- XML:在早期的网络传输中主要是使用XML来进行数据交换的,但是这种格式在解析、传输等各方面都弱于JSON,所以目前已经很少在被使用了;
- Protobuf:另外一个在网络传输中目前已经越来越多使用的传输格式是protobuf,但是直到2021年的3.x版本才支持JavaScript,所以目前在前端使用的较少。
- 目前JSON被使用的场景也越来越多:
- 网络数据的传输JSON数据;
- 项目的某些配置文件;
- 非关系型数据库(NoSQL)将json作为存储格式。
2. JSON的基本语法
- JSON的顶层支持三种类型的值:
- 简单值:数字(Number)、字符串(String,不支持单引号)、布尔类型(Boolean)、null类型;
- 对象值:由key、value组成,key是字符串类型,并且必须添加双引号,值可以是简单值、对象值、数组值;
- 数组值:数组的值可以是简单值、对象值、数组值。 注意:json文件不能有注释。
- JSON序列化
- 某些情况下我们希望将JavaScript中的复杂类型转化成JSON格式的字符串,这样方便对其进行处理:
- 比如我们希望将一个对象保存到localStorage中;
- 但是如果我们直接存放一个对象,这个对象会被转化成 [object Object] 格式的字符串,并不是我们想要的结果。
- 在ES5中引用了JSON全局对象,该对象有两个常用的方法:
- stringify方法:将JavaScript类型转成对应的JSON字符串;
- parse方法:解析JSON字符串,转回对应的JavaScript类型。
const obj = {
name: 'aaa',
info: {
name: 'bbb'
}
}
const objString = JSON.stringify(obj)
console.log(typeof objString) //string
console.log(objString) //{ name: 'aaa', info: { name: 'bbb' } }
console.log(typeof JSON.parse(objString)) //object
console.log(JSON.parse(objString)) //{ name: 'aaa', info: { name: 'bbb' } }
- 序列化方法 stringify 的细节
- stringify的第二个参数replacer
- JSON.stringify() 方法将一个 JavaScript 对象或值转换为 JSON 字符串:
- 如果指定了一个 replacer 函数,则可以选择性地替换值;
- 如果指定的 replacer 是数组,则可选择性地仅包含数组指定的属性。
- JSON.stringify() 方法将一个 JavaScript 对象或值转换为 JSON 字符串:
const obj = {
name: 'aaa',
info: {
name: 'bbb'
}
}
// 1、stringify的第二个参数replacer
// 1.1函数
const objString = JSON.stringify(obj, (key, value) => {
if (key === 'info') {
return 'ccc'
}
return value
})
console.log(objString) //{"name":"aaa","info":"ccc"}
// 1.2数组:设定哪些是需要转换
// info对象中的属性也要符合数组里的值,才能选择性地仅包含数组指定的属性
const objString2 = JSON.stringify(obj, ['info'])
console.log(objString2) //{"info":{}}
const objString3 = JSON.stringify(obj, ['name', 'info'])
console.log(objString3) //{"name":"aaa","info":{"name":"bbb"}}
- stringify的第三个参数space
const obj = {
name: 'aaa',
info: {
name: 'bbb'
}
}
// stringify第三参数 space,格式缩进的替换字符,可以是空格等
const jsonString = JSON.stringify(obj, null, '---')
console.log(jsonString)
/* {
---"name": "aaa",
---"info": {
------"name": "bbb"
---}
} */
- 如果对象本身包含toJSON方法,那么会直接使用toJSON方法的结果
const obj = {
name: 'aaa',
info: {
name: 'bbb'
},
toJSON: function () {
return '直接使用toJSON方法的结果'
}
}
const jsonString = JSON.stringify(obj)
console.log(jsonString) //"直接使用toJSON方法的结果"
- 序列化方法 parse 的细节
- JSON.parse() 方法用来解析JSON字符串,构造由字符串描述的JavaScript值或对象
- 提供可选的 reviver 函数用以在返回之前对所得到的对象执行变换(操作)。
const jsonString = '{"name":"aaa","info":{"name":"bbb"}}'
const obj = JSON.parse(jsonString, (key, value) => {
if (key === 'info') {
return 'ccc'
}
return value
})
console.log(obj) //{ name: 'aaa', info: 'ccc' }
- 使用JSON序列化深拷贝
const obj = {
name: 'aaa',
info: {
name: 'bbb'
},
foo: function () {
console.log('foo function')
}
}
// 将obj对象的内容放到aaa变量中
// 1.引用赋值
const aaa = obj
obj.name = 'ccc'
console.log(aaa.name) //ccc
// 2.浅拷贝
const aaa2 = { ...obj }
obj.name = 'ddd'
console.log(aaa2.name) //打印出 1.引用赋值 中修改的值:ccc
//这里没有实现深拷贝,所以会变
obj.info.name = 'xxx'
console.log(aaa2.info.name) //xxx
// 3.stringify和parse来实现深拷贝
// 注意:这种方法它对函数是无能为力的
const jsonString = JSON.stringify(obj)
console.log(jsonString) //{"name":"ddd","info":{"name":"xxx"}}
const aaa3 = JSON.parse(jsonString)
console.log(aaa3) //{ name: 'ddd', info: { name: 'xxx' } }
//这里实现了深拷贝,所以不会变
obj.info.name = 'yyy'
console.log(aaa3.info.name) //打印出 2.浅拷贝 中修改的值:xxx
- 注意:这种方法它对函数是无能为力的
- 这是因为stringify并不会对函数进行处理。
- 上面的浅拷贝也就是obj里面的值复制一份给了另一个对象,所以aaa2和obj的地址指向不是同一个对象,但是obj中的info和aaa2中的info指向还是同一个对象。深拷贝就是使obj中的info和aaa2中的info指向不是同一个对象。