问题

如题,js 中对象 json 序列化方法 JSON.stringfy() 输出非空对象结果为 '{}'

想要获取移动端当前的网络类型,在网上找到两个方法,一个是借助 navigator.userAgent 里面包含的 NetType 信息判断,还有一个是 navigator.connection 中的 type 字段判断的。

测试结果一直不如意,开始怀疑判断所依据的字段或者字符串并不存在。而对于 navigator 中除了 ua 之外还有哪些信息并不知道,所以想输出全局变量 navigator 看一下。

alert(JSON.stringfy(navigator)) 结果一直为 '{}'。虽然通过 console.log(navigator) 输出对象内容,得到了我想要的东西,但我还是好奇,为什么在 js 中专门用来序列化对象的 JSON.stringfy() 会不起作用。

解决

网上查看了一下资料,你可能不知道的 JSON.stringfy 用法。里面提到,JSON.stringfy() 用途广泛,很多 js 框架底层的 toJson() 都用了这个来实现的。但是它本身对于某些值的处理是出乎意料的,比如说,JSON.stringify() 会将 NaNInfinity 转化为 null:

const obj = { nan: parseInt('not a number'), inf: Number.POSITIVE_INFINITY };

JSON.stringify(obj); // '{"nan":null,"inf":null}'

还有一种会抛出错误异常的情况:

const obj = {};
// 存在循环引用的对象,它指向它本身
obj.prop = obj;

// 会抛出 "TypeError: TypeError: Converting circular structure to JSON" 异常
JSON.stringify(obj);

并且,JSON.stringify() 也会直接省略那些值为 functions 和 undefined 的属性,如下:

const obj = { fn: function() {}, undef: undefined };

// 它会返回空对象
JSON.stringify(obj); // '{}'

所以,json 序列化返回 '{}',就是因为 navigator 并不是一个纯粹的数据,它内部包含了一些 functions。

这样自然就不能通过 JSON.stringify(obj) 输出查看到对象内容了。