读Ext之十(解析JSON)
首先,回到第一篇。使用Ext.apply为Ext对象添加了一些属性,
1 2 3 4 5 | Ext.apply(Ext, { ... USE_NATIVE_JSON : false , ... }); |
USE_NATIVE_JSON 即为其中之一, 可以使用它来设置是否开启浏览器原始的JSON(即JSON.parse,JSON.stringify)来解析或反解析。这是ECMA5中加入的,在 字符串转换成JSON的三种方式中已经提到。
该值初始为false,即不开启。设置为true则开启如
Ext.USE_NATIVE_JSON = true;
Ext.util.JSON 内部定义了一些私有方法,对外公开的有三个方法
encodeDate 将日期对象转成字符串
encode 将JS对象转成字符串
decode 将字符串转成JS对象
此外,encode和decode分别赋值给了Ext.encode和Ext.decode。如
1 2 | Ext.encode = Ext.util.JSON.encode; Ext.decode = Ext.util.JSON.decode; |
即开发时可以使用更简短的Ext.encode和Ext.decode而非冗长的Ext.util.JSON.encode和Ext.util.JSON.decode。
Ext.util.JSON的大体结构如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | Ext.util.JSON = new ( function (){ var useHasOwn = !!{}.hasOwnProperty, isNative = function () { var useNative = null ; return function () { if (useNative === null ) { useNative = Ext.USE_NATIVE_JSON && window.JSON && JSON.toString() == '[object JSON]' ; } return useNative; }; }(), ... ; this .encodeDate = function (o){ }; this .encode = function () { }(); this .decode = function () { }(); })(); |
可看到new了一个匿名函数(类),即Ext.util.JSON为一个单体。
匿名类中定义了一些私有变量useHasOwn、isNative等,this上挂了三个方法,即上面提到的对外公开的三个接口方法。
isNative 函数用来判断是否开启浏览器原始解析JSON的API,当然该函数只在Ext.USE_NATIVE_JSON为true的时候起作用,否则永远使用私有的doDecode和doEncode来解析。
1 2 3 4 5 6 7 8 9 | isNative = function () { var useNative = null ; return function () { if (useNative === null ) { useNative = Ext.USE_NATIVE_JSON && window.JSON && JSON.toString() == '[object JSON]' ; } return useNative; }; }(), |
pad 函数用来计算日期,所传参数n小于10时添加个0, 如月份传3时返回03,自动补个0。 this.encodeDate方法中用到。
1 2 3 | pad = function (n) { return n < 10 ? "0" + n : n; }, |
doDecode 函数将字符转成JS对象,这里采用eval方式,当然还可以使用new Function。
1 2 3 | doDecode = function (json){ return eval( "(" + json + ')' ); }, |
别忘了eval中两旁的小括号,否则会有意想不到的bug。为何加小括号见:JavaScript中大括号“{}”的多义性
doEncode 函数将JS对象转换成符合JSON规范的字符串,这个函数比较复杂。先对基本类型和数组,日期进行转换,最后是对JS对象的处理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | doEncode = function (o){ if (!Ext.isDefined(o) || o === null ){ return "null" ; } else if (Ext.isArray(o)){ return encodeArray(o); } else if (Ext.isDate(o)){ return Ext.util.JSON.encodeDate(o); } else if (Ext.isString(o)){ return encodeString(o); } else if ( typeof o == "number" ){ //don't use isNumber here, since finite checks happen inside isNumber return isFinite(o) ? String(o) : "null" ; } else if (Ext.isBoolean(o)){ return String(o); } else { var a = [ "{" ], b, i, v; for (i in o) { // don't encode DOM objects if (!o.getElementsByTagName){ if (!useHasOwn || o.hasOwnProperty(i)) { v = o[i]; switch ( typeof v) { case "undefined" : case "function" : case "unknown" : break ; default : if (b){ a.push( ',' ); } a.push(doEncode(i), ":" , v === null ? "null" : doEncode(v)); b = true ; } } } } a.push( "}" ); return a.join( "" ); } }, |
doEncode中对字符串的转换用到了encodeString及encodeArray函数。
最后是三个挂在this上的方法,以this.decode示例
1 2 3 4 5 6 7 8 9 10 | this .decode = function () { var dc; return function (json) { if (!dc) { // setup decoding function on first access dc = isNative() ? JSON.parse : doDecode; } return dc(json); }; }(); |
dc = isNative() ? JSON.parse : doDecode 可以看到如果isNative()返回true则使用浏览器原始的JSON.parse,否则使用doDecode。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端
2011-05-01 JS Queue LazyLoad 之一
2011-05-01 JS/CSS module LazyLoad 之三