JSON.stringify
1. 九大特性
const data = {
a: 'aaa',
b: undefined,
c: Symbol('dd'),
fn: function () { return true; }
};
JSON.stringify(data); // '{"a":"aaa"}'
1.1 忽略 undefined / 函数 / Symbol
JSON.stringify(['aaa', undefined, function aa() {}, Symbol('dd')]);
// '["aaa",null,null,null]'
在数组里,它们被序列化为
null;在对象里则直接被忽略。
1.2 顶层 undefined / 函数 / Symbol → undefined
JSON.stringify(function a() { console.log('a'); }); // undefined
JSON.stringify(undefined); // undefined
JSON.stringify(Symbol('dd')); // undefined
1.3 序列化结果顺序不一定保证
由于会忽略部分特殊值,所以不能保证序列化后字段顺序与原对象一致(数组除外)。
const data = {
a: 'aaa', b: undefined,
c: Symbol('dd'),
fn: function () { return true; },
d: 'ddd'
};
JSON.stringify(data); // '{"a":"aaa","d":"ddd"}'
1.4 toJSON 方法优先
如果对象定义了 toJSON,则使用 toJSON 的返回值。
JSON.stringify({
say: 'hello JSON.stringify',
toJSON() { return 'today i learn'; }
}); // '"today i learn"'
JSON.stringify({ now: new Date() }); // '{"now":"2019-12-08T07:42:11.973Z"}'
1.5 NaN / Infinity / null → null
JSON.stringify(NaN); // 'null'
JSON.stringify(null); // 'null'
JSON.stringify(Infinity); // 'null'
1.6 包装对象自动拆箱
JSON.stringify([new Number(1), new String('false'), new Boolean(false)]);
// '[1,"false",false]'
1.7 不可枚举属性默认忽略
JSON.stringify(
Object.create(null, {
x: { value: 'json', enumerable: false },
y: { value: 'stringify', enumerable: true }
})
);
// '{"y":"stringify"}'
1.8 不能处理循环引用
const a = {};
a.self = a;
JSON.stringify(a); // TypeError: Converting circular structure to JSON
JSON.parse(JSON.stringify())这种"深拷贝"也会因循环引用直接抛错。
1.9 Symbol 作为 key 时,replacer 无法拦截
JSON.stringify({ [Symbol.for('json')]: 'stringify' }, function (k, v) {
if (typeof k === 'symbol') return v;
}); // undefined(Symbol 属性被忽略)
2. 强大的第二个参数:replacer
replacer 可为函数或数组。
作为函数
(key, value) => newValue,对每个属性值执行一次。
const data = {
a: 'aaa',
b: undefined,
c: Symbol('dd'),
fn: function () { return true; }
};
JSON.stringify(data, (key, value) => {
switch (true) {
case typeof value === 'undefined': return 'undefined';
case typeof value === 'symbol': return value.toString();
case typeof value === 'function': return value.toString();
default: break;
}
return value;
});
// '{"a":"aaa","b":"undefined","c":"Symbol(dd)","fn":"function() {\n return true;\n }"}'
注意:
replacer函数第一次被调用时,key是空字符串,value是整个对象。
作为数组
数组里的值表示将被序列化的属性名:
const jsonObj = {
name: 'JSON.stringify',
params: 'obj,replacer,space'
};
JSON.stringify(jsonObj, ['params']);
// '{"params":"obj,replacer,space"}'
3. 第三个参数:space(美化输出)
JSON.stringify({ a: 1, b: 2 }, null, 2);
// '{\n "a": 1,\n "b": 2\n}'
来源整理自:我的有道云笔记



