JSON.stringify方法

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两种方式实现。

【参考资料】

Using JavaScript’s JSON.stringify

MDN’s JSON.stringify()

猜你喜欢

转载自blog.csdn.net/u013137242/article/details/80933015