看到一个有意思的问题:定义一个对象,他们的value包括null,undefined,function(){},Symbol(),问他们的JSON.stringify结果是多少?

    1. var a={
    2.     key1:'name',
    3.     key2:null,
    4.     key3:undefined,
    5.     key4:function(){},
    6.     key5:Symbol()
    7. }
    8. JSON.stringify(a);

    开始我以为很简单,没想到这里面还有坑。。。而且坑还很深,今天我们就看看看JSON.stringify的一些规则:

    当JSON.stringify的对象的value为undefined,Function,Symbol的时候,会直接忽略(JSON.stringify第二个参数可以指定)。

    这个就是上面的例子,最后的结果是"{"key1":"name","key2":null}"。

    这里虽然会被忽略,但是JSON.stringify有第二个参数可以额外执行返回结果,看看下面的例子就知道了:

    1. var obj={key1:'aaa',key2:Symbol()};
    2. JSON.stringify(obj,(key,value)=>{
    3.     return typeof value=='symbol'?'symbol':value;
    4. });
    5. /*
    6. 结果:
    7. "{"key1":"aaa","key2":"symbol"}"
    8. */

    本来如果value为Symbol不返回,这里判断类型,然后强制返回了一个字符串symbol。(注意,JSON.stringify第二个参数如果是方法的时候一定要有返回值,否则不能完成遍历)。

    当JSON.stringify的数组里面包含undefined,Function,Symbol的时候,返回null。

    看个例子:

    1. JSON.stringify(['name',function(){},null,Symbol()]);
    2. /*
    3. 结果
    4. "["name",null,null,null]"
    5. */

    当JSON.stringify的对象的key为Symbol的时候,会被完全忽略(JSON.stringify第二个参数无法指定),

    1. var obj={name:'aaa'},symbol=Symbol();
    2. obj[symbol]='bbb';
    3. JSON.stringify(obj,(key,value)=>{
    4.     console.log(key,value);
    5.     return value;
    6. });

    根据上面的例子我们可以知道,如果JSON.stringify不返回可以通过第二个参数方法指定,但是如果key为Symbol的时候,遍历的时候是无法遍历到的,因此也就无法返回了。

    JSON.stringify如果遇到不可枚举类型,忽略。

    1. var obj=Object.create(null,{
    2.     x:{
    3.         value:'x',
    4.         enumerable:false    
    5.     },
    6.     y:{
    7.         value:'y',
    8.         enumerable:true
    9.     }
    10. });
    11. JSON.stringify(obj);

    因为不可枚举类型的key也是无法遍历到的,因此也无法操作返回。

    其他注意的点:

    JSON.stringify第二个参数除了指定一个方法,还可以是一个数组,这样可以指定key进行字符串化(前提是正常可以转的,如果遇到特殊另当别论)。

    1. var obj={key1:'a',key2:'b',key3:'c'};
    2. JSON.stringify(obj,['key1','key3']);
    3. /*
    4. 结果:
    5. "{"key1":"a","key3":"c"}"
    6. */

    上面的例子中指定了key1和key3,那么key2就不会在结果里面。

    JSON.stringify还有第三个参数,这个参数是用来控制返回结果的样式的,看个简单的demo:

    1. var obj={key1:'a',key2:'b',key3:'c'};
    2. JSON.stringify(obj,null,10);
    3. /*
    4. 结果:
    5. "{
    6.     "key1": "a",
    7.     "key2": "b",
    8.     "key3": "c"
    9. }"
    10. */
    11. JSON.stringify(obj,null,‘aaa‘);
    12. /*
    13. 结果:
    14. "{
    15. aaa"key1": "a",
    16. aaa"key2": "b",
    17. aaa"key3": "c"
    18. }"
    19. */

    如果第三个参数为数组(最多为10),那么每个每次换行都会空10格子。

    如果第三个参数为字符串(最多10个,例如'aaa','\t'等),那么每个每次换行都会填充它们。

    如果JSON.stringify的对象本身有toJSON方法,那么直接调用toJSON方法:

    1. var obj={key1:'a',key2:'b',key3:'c',toJSON:function(){return 'toJSON';}};
    2. JSON.stringify(obj);
    3. /*
    4. 结果:
    5. "toJSON"
    6. */

    同理,JSON.parse有两个参数,其中第二个参数里面也是用来指定key,value的。

    1. var obj={a:'1',b:'2'};
    2. JSON.parse(JSON.stringify(obj),(key,value)=>{
    3.     console.log(key,value);
    4.     return typeof value!='object'?value*2:value ;
    5. });
    6. /*
    7. 结果:
    8. {a: 2, b: 4}
    9. */

    上面的代码将一个对象里面的数字翻了一倍。

    回到顶部
    我要评论

    所有评论

      相关文章