jQuery1.3代码深度分析,clean

// 把html转换成Dom元素,elems多个html string 的数组1.2.6得时候只有两个参数,新的版本中加了fragment第三个参数

clean: function( elems, context, fragment ) {

context = context || document;

//默认的上下文是document

//在IE中!context.createElement行不通,因为它返回对象类型

// !context.createElement fails in IE with an error but returns typeof 'object'

if ( typeof context.createElement === "undefined" )

//这里支持context为jQuery对象,取第一个元素。

context = context.ownerDocument || context[0] && context[0].ownerDocument || document;

// If a single string is passed in and it's a single tag

// just do a createElement and skip the rest

//这是1.3新加的,如果是单独得标签比如:$('<div />') 直接调用createElement

if ( !fragment && elems.length === 1 && typeof elems[0] === "string" ) {

var match = /^<(\w+)\s*\/?>$/.exec(elems[0]);

if ( match )

return [ context.createElement( match[1] ) ];

}

var ret = [], scripts = [], div = context.createElement("div");

jQuery.each(elems, function(i, elem){

if ( typeof elem === "number" )

elem += '';

// 把int 转换成string的最高效的方法

if ( !elem )

return;

// Convert html string into DOM nodes // 转换html为Dom元素

if ( typeof elem === "string" ) {

// Fix "XHTML"-style tags in all browsers

// 修正 "XHTML"-style 标签,对于如<div/>的形式修改为<div></div>

//但是对于(abbr|br|col|img|input|link|meta|param|hr|area|embed)不修改

//front=(<(\w+)[^>]*?)

elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){

return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ?

all :

front + "></" + tag + ">";

});

// Trim whitespace, otherwise indexOf won't work as expected

// 去空格,否则indexof不能正常工作

var tags = jQuery.trim( elem ).toLowerCase();

// 有些标签必须是有一些约束的,比如<option>必须在<select></select>中间

// 下面的代码在大部分是对<table>中子元素进行修正。数组中第一个元素为深度

//&&>||

var wrap =

// option or optgroup

!tags.indexOf("<opt") &&

[ 1, "<select multiple='multiple'>", "</select>" ] ||

!tags.indexOf("<leg") &&

[ 1, "<fieldset>", "</fieldset>" ] ||

tags.match(/^<(thead|tbody|tfoot|colg|cap)/) &&

[ 1, "<table>", "</table>" ] ||

!tags.indexOf("<tr") &&

[ 2, "<table><tbody>", "</tbody></table>" ] ||

// <thead> matched above

(!tags.indexOf("<td") || !tags.indexOf("<th")) &&

[ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] ||

!tags.indexOf("<col") &&

[ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] ||

// IE can't serialize <link> and <script> tags normally

!jQuery.support.htmlSerialize &&

[ 1, "div<div>", "</div>" ] ||

[ 0, "", "" ];

// Go to html and back, then peel off extra wrappers

// 包裹html之后,采用innerHTML转换成Dom

div.innerHTML = wrap[1] + elem + wrap[2];

// Move to the right depth

while ( wrap[0]-- )

div = div.lastChild;

// Remove IE's autoinserted <tbody> from table fragments

if ( !jQuery.support.tbody ) {

// String was a <table>, *may* have spurious <tbody>

var tbody = !tags.indexOf("<table") && tags.indexOf("<tbody") < 0 ?

div.firstChild && div.firstChild.childNodes :

// String was a bare <thead> or <tfoot>

wrap[1] == "<table>" && tags.indexOf("<tbody") < 0 ?

div.childNodes :

[];

for ( var j = tbody.length - 1; j >= 0 ; --j )

if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length )

tbody[ j ].parentNode.removeChild( tbody[ j ] );

}

// IE completely kills leading whitespace when innerHTML is used

if ( !jQuery.support.leadingWhitespace && /^\s/.test( elem ) )

div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild );

elem = jQuery.makeArray( div.childNodes );

}

if ( elem.nodeType )

ret.push( elem );

else

ret = jQuery.merge( ret, elem );

});

//这段是新加的处理js代码,同时也取消了form的处理

if ( fragment ) {

for ( var i = 0; ret[i]; i++ ) {

if ( jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {

scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );

} else {

if ( ret[i].nodeType === 1 )

ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) );

fragment.appendChild( ret[i] );

}

}

return scripts;

}

return ret;

},

},

这 个方法主要解决html到dom的转换,在1.3选择器中接着比较重要就是xpath的选择了。以前得版本是自己写的,新得版本是整合了Sizzle,类 似jQuery.find=Sizzle.find,这样代码重载jQuery得选择器,下节再讲Sizzle,实际上选择得原理和1.2.6是一样的, 只是有点细节上的区别。