jQuery源码阅读6:xml和json解析

还是拆解第一次jQuery.extend, 这次阅读json和xml相关的解析
除了这一波 , 工具函数里还有proxy,access,和ready没读
ready用到了jQuery的队列处理, 打算读完Deferred那块再拆解

这对转换用正则比较多, 今天应该还有点儿时间, 打算补一补正则

1.parseXML

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
//解析XML
parseXML: function( data ) {
var xml, tmp;
if ( !data || typeof data !== "string" ) {
return null;//空返回null
}
try {
//标准浏览器用window.DOMParser处理
if ( window.DOMParser ) {
tmp = new DOMParser();
//原生的DOMParser.parseFromString
//这必须用new出来的DOMParser,而且作用域也得是刚new出来的对象,用call就比较蛋疼了tmp.parseFromString.call(tmp,data,"text/xml")
xml = tmp.parseFromString( data , "text/xml" );//第二个参数类型貌似还能转别的
} else {
//低版本IE用ActiveXObject
xml = new ActiveXObject( "Microsoft.XMLDOM" );
xml.async = "false";
xml.loadXML( data );
}
} catch( e ) {
//chrome里,解析出错也xml也会是一个document,里边是个<a>出错内容</a>
xml = undefined;
}
//出错抛一个异常Invalid XML+传参, 兼容处理DOMParser和ActiveXObject
if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
jQuery.error( "Invalid XML: " + data );
}
return xml;
},

2.parseJSON

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
/**
* 博文作者:ruantao1989@gmail.com
* 引自博客:ruantao.duapp.com/blog
*/
// JSON RegExp
rvalidchars = /^[\],:{}\s]*$/,//这个正则只能看懂一点...
rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,
rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,
//==>源码504行
parseJSON: function( data ) {
if ( !data || typeof data !== "string") {
return null;
}
//官方注释:IE处理不了空格
data = jQuery.trim( data );
//标准浏览器调用JSON.parse
if ( window.JSON && window.JSON.parse ) {
return window.JSON.parse( data );
}
//用上述4个正则校验是不是正确的json
if ( rvalidchars.test( data.replace( rvalidescape, "@" )
.replace( rvalidtokens, "]" )
.replace( rvalidbraces, "")) ) {
//json格式校验通过
//new Function是用字串创建一个匿名函数, 内容就是return "JSON",并且立即执行
//这样就挺巧妙的用字面量生成了一个Object, 避免用eval()了
return ( new Function( "return " + data ) )();
}
//到这证明json校验没通过, 或是转换出错
//统一抛个异常
jQuery.error( "Invalid JSON: " + data );
},

3.globalEval

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//匹配非空白符的正则, 这个能看懂 哈
core_rnotwhite = /\S/,
//在全局作用域里执行js代码,
//这个源代码中选择器用了一次, 动态加载用了一次, 不太明白什么场景会有用
globalEval: function( data ) {
if ( data && core_rnotwhite.test( data ) ) {
//支持window.execScript的用(window.execScript)(data)
//不支持的window[ "eval" ].call( window, data );
//这个写法很简洁,也易读
//关于window[ "eval" ]这个写法应该是游浏览器兼容问题
( window.execScript || function( data ) {
window[ "eval" ].call( window, data );
} )( data );
}
},

4.parseHTML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//html标签正则: 以<开头 跟至少一个文字 跟若干空格 ,后边语法看不懂了...,正则的细节以后单开个文章学吧
rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/,
//把传入的html字串解析成数组, 只有选择器里用了一次
parseHTML: function( data, context, scripts ) {
var parsed;
if ( !data || typeof data !== "string" ) {
return null;
}
if ( typeof context === "boolean" ) {//上下文如果是布尔型
scripts = context;
context = 0;
}
context = context || document;//上下文默认是document
//parsed是正则生成的html标签数组
if ( (parsed = rsingleTag.exec( data )) ) {
return [ context.createElement( parsed[1] ) ];//createElement创建标签
}
//生成选择器所需的数组,并合并
parsed = jQuery.buildFragment( [ data ], context, scripts ? null : [] );
return jQuery.merge( [],
(parsed.cacheable ? jQuery.clone( parsed.fragment ) : parsed.fragment).childNodes );
},