JSON.stringify方法对正则的处理
看Sizzle的时候,用JSON.stringify方法输出了一下RegExp
,结果是个空对象{}
。一脸茫然。。。。。 一脸懵逼???黑人问号.png
JSON.stringify({r: /abc/});
// '{"r":{}}'
JSON.stringify(/abc/);
// "{}"
那么我们看看RegExp.prototype.toString()
方法的输出结果是否是预期的呢?
/abc/.toString(); // "/abc/" 没问题,
Array也是对象,我们都知道JSON.stringify 是会将Array中的元素转成字符串输出的。
JSON.stringify(['a', 'b', 'c']); // '["a","b","c"]'
Array 和 RegExp同是衍生对象,为啥这么不同命呢?
为啥JSON.stringify
方法为什么不会在处理RegExp
对象时,调用RegExp自身的toString方法呢?
JSON.stringify不支持的数据类型
JSON.stringify会处理的几种类型: String, Number, Boolean, null, Array, Object
不会处理的几种类型: Date, RegExp, undefined, Function
var o = {
n: 1,
s: 'abc',
b: true,
empty: null,
a: [1,2,3],
o:{ a: 1},
d: new Date(),
r: /abc/,
u: undefined,
f: function(){}
}
console.log(JSON.stringify(o));
// {"n":1,"s":"abc","b":true,"empty":null,"a":[1,2,3],"o":{"a":1},"d":"2018-07-05T02:49:37.194Z","r":{}}
可以看到,支持的类型都被处理了; 不支持的类型中,Date类型被转成了字符串输出,正则表达式转成了空对象, undefined和Function都被直接忽略了。
replacer
先不解释为什么Date属于不支持的类型,但是确能被转成UTC时间的问题。
我们来聊聊 JSON.stringify方法中的第二个可选参数 replacer
。
如果该参数是一个函数,则在序列化过程中,被序列化的值的每个属性都会经过该函数的转换和处理;如果该参数是一个数组,则只有包含在这个数组中的属性名才会被序列化到最终的 JSON 字符串中;如果该参数为null或者未提供,则对象所有的属性都会被序列化;
对于JSON.stringify不支持的数据类型,我们推荐使用replacer
来处理。
JSON.stringify({r: /abc/}, function(k, v){
if(v instanceof RegExp){
return v.toString();
}
return v;
});
// '{"r":"/abc/"}'
toJSON方法
如果一个被序列化的对象拥有 toJSON 方法,那么该 toJSON 方法就会覆盖该对象默认的序列化行为:不是那个对象被序列化,而是调用 toJSON 方法后的返回值会被序列化。这也是JSON.stringify在处理Date类型时,能够输出字符串的原因————因为Date类型本身被实现了toJSON方法。
RegExp.prototype.toJSON = RegExp.prototype.toString;
JSON.stringify({r: /abc/});
// '{"r":"/abc/"}'
总结
现在我们回到开头说的正则类型转换问题,想要解决的话可以通过replacer和toJSON两种方式实现。
【参考资料】