这篇文章主要介绍了JSON.stringify知识点。
1. 定义
stringify
函数的定义: JSON.stringify(value [, replacer [, space]])
参数:
- value : 将要转为JSON字符串的javascript对象。
- replacer :该参数可以是多种类型,如果是一个函数,则它可以改变一个javascript对象在字符串化过程中的行为, 如果是一个包含 String 和 Number 对象的数组,则它将作为一个白名单.只有那些键存在域该白名单中的键值对才会被包含进最终生成的JSON字符串中.如果该参数值为null或者被省略,则所有的键值对都会被包含进最终生成的JSON字符串中。
- space :该参数可以是一个 String 或 Number 对象,作用是为了在输出的JSON字符串中插入空白符来增强可读性. 如果是Number对象, 则表示用多少个空格来作为空白符; 最大可为10,大于10的数值也取10.最小可为1,小于1的数值无效,则不会显示空白符. 如果是个 String对象, 则该字符串本身会作为空白符,字符串最长可为10个字符.超过的话会截取前十个字符. 如果该参数被省略 (或者为null), 则不会显示空白符
1.1 替换函数可以用来过滤值
- 返回 undefined 表示忽略该属性
- 返回字符串,布尔值或则数字将会被 stringify
- 返回对象将会触发递归调用知道遇到基本类型的属性
- 返回无法 stringify 的值将会被忽略
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| let user = { age: 18, name: 'tom', email: 'tom@caonima.com' }; function replacer(key, value) { if (key === 'email') { return undefined; } return value; } let str = JSON.stringify(user, replacer);
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| let data = [ {name: "tom", sex:1, age: 18}, {name: "jerry", sex:0, age: 17}, {name: "mike", test: {age: 15}} ];
let str = JSON.stringify(data, ["name","age"]); console.log(str);
let str2 = JSON.stringify(data, function(key, val){ if(key === 'sex'){ return ['男', '女'][val] } return val }) console.log(str2);
|
1.2 使用 JSON.stringify()
做对象序列化
- undefined 值、函数或者XML值会被忽略
- 如果你的数组当中含有 undefined值,函数或XML值,该数组中的这些值将会被当成 null
- 如果属性为
null
则可以正常序列化这个属性(因为 null
可表示已经赋值,而 undefined
表示未定义、未赋值,所以执行 JSON.stringify
不会处理。)
- 有些属性无法被
stringify
(SON 是一个通用的文本格式,和语言无关。设想如果将函数定义也 stringify 的话,如何判断是哪种语言,并且通过合适的方式将其呈现出来将会变得特别复杂。特别是和语言相关的一些特性,比如 JavaScript 中的 Symbol。)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| let data = { name: 'tom', age: undefined, sex: null, fn: function() { return true } } JSON.stringify(data)
let arr = [Symbol(), undefined, function() {}, "tom"]; JSON.stringify(arr);
|
1.3 使用JSON.parse(JSON.stringify(obj))实现深拷贝
JSON.parse(JSON.stringify(obj))
我们一般用来深拷贝,其过程说白了 就是利用JSON.stringify 将js对象序列化(JSON字符串),再使用JSON.parse来反序列化(还原)js对象;序列化的作用是存储(对象本身存储的只是一个地址映射,如果断电,对象将不复存在,因此需将对象的内容转换成字符串的形式再保存在磁盘上 )和传输(例如 如果请求的Content-Type
是 application/x-www-form-urlencoded
,则前端这边需要使用qs.stringify(data)
来序列化参数再传给后端,否则后端接受不到; ps: Content-Type
为 application/json;charset=UTF-8
或者 multipart/form-data
则可以不需要 );我们在使用 JSON.parse(JSON.stringify(xxx))
时应该注意一下几点:
- 如果obj里面有时间对象,则JSON.stringify后再JSON.parse的结果,时间将只是字符串的形式。而不是时间对象;
- 如果obj里有RegExp、Error对象,则序列化的结果将只得到空对象;
- 如果obj里有函数,undefined,则序列化的结果会把函数或 undefined丢失;
- 如果obj里有NaN、Infinity和-Infinity,则序列化的结果会变成null
- JSON.stringify()只能序列化对象的可枚举的自有属性,例如 如果obj中的对象是有构造函数生成的, 则使用JSON.parse(JSON.stringify(obj))深拷贝后,会丢弃对象的constructor;
- 如果对象中存在循环引用的情况也无法正确实现深拷贝;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| function deepClone(data) { const type = this.judgeType(data); let obj; if (type === 'array') { obj = []; } else if (type === 'object') { obj = {}; } else { return data; } if (type === 'array') { for (let i = 0, len = data.length; i < len; i++) { obj.push(this.deepClone(data[i])); } } else if (type === 'object') { for (const key in data) { obj[key] = this.deepClone(data[key]); } } return obj; },
function judgeType(obj) { const map = { '[object Boolean]': 'boolean', '[object Number]': 'number', '[object String]': 'string', '[object Function]': 'function', '[object Array]': 'array', '[object Date]': 'date', '[object RegExp]': 'regExp', '[object Undefined]': 'undefined', '[object Null]': 'null', '[object Object]': 'object', }; if (obj instanceof Element) { return 'element'; } return map[Object.prototype.toString.call(obj)]; },
|
注意
- 不是所有的合法的 JSON 都是有效的 JavaScript
- JSON 只是一个文本格式
- JSON 中的数字是十进制