// Global undefined variable
window.undefined = window.undefined;
function jQuery(a,c) {
// Shortcut for document ready (because $(document).each() is silly)
/*
举例: jQuery(function(){alert('All Tags Finished');}
*/
if ( a && a.constructor == Function && jQuery.fn.ready )
return jQuery(document).ready(a);
// Make sure that a selection was provided
a = a || jQuery.context || document;
// Watch for when a jQuery object is passed as the selector
/*jquery: "$Rev: 509 ";,判断是否为jQuery的包装集可以利用该参数,该参数在后来返回其版本号 */
if ( a.jquery )
return $( jQuery.merge( a, [] ) ); /*jQuery.merge合并两个数组,不重复相同元素*/
// Watch for when a jQuery object is passed at the context
if ( c && c.jquery )
return $( c ).find(a);
// If the context is global, return a new object
/*第一次以函数的身份执行,第二次以类的名义操作*/
if ( window == this )
return new jQuery(a,c);
// Handle HTML strings
/*遇到html标签,比如<div>
* clean函数,见425行
* */
var m = /^[^<]*(<.+>)[^>]*$/.exec(a);
if ( m ) a = jQuery.clean( [ m[1] ] );
// Watch for when an array is passed in
this.get( a.constructor == Array || a.length && !a.nodeType && a[0] != undefined && a[0].nodeType ?
// Assume that it is an array of DOM Elements
jQuery.merge( a, [] ) :
// Find the matching elements and save them for later
/*选择符一般从这儿开始正式步入查找阶段*/
jQuery.find( a, c ) );
// See if an extra function was provided
/*有额外参数为函数的情况*/
var fn = arguments[ arguments.length - 1 ];
// If so, execute it in context
if ( fn && fn.constructor == Function )
this.each(fn);
}
jQuery定义为类,上面这个类考虑到的参数是各种形式(函数,包装集,字符串等),如果遇到不符合条件的tag,首选调用clean函数来修复这个tag,clean函数代码如下:
/*修正html标签,功能包括关闭标签、自动转小写、自动删除不被识别的标签、格式化缩进等*/
/*后面的?*/
clean: function(a) {
var r = [];
for ( var i = 0; i < a.length; i++ ) {
if ( a[i].constructor == String ) {
// 如果是表格元素,修正该元素
var table = "";
/*如果存在thead或者tbody在第一位*/
if ( !a[i].indexOf("<thead") || !a[i].indexOf("<tbody") ) {
table = "thead";
a[i] = "<table>" + a[i] + "</table>";
}
/*如果存在tr并且在第一位,注意-1为true*/
else if ( !a[i].indexOf("<tr") ) {
table = "tr";
a[i] = "<table>" + a[i] + "</table>";
}
/*如果存在th,在第一位*/
else if ( !a[i].indexOf("<td") || !a[i].indexOf("<th") ) {
table = "td";
a[i] = "<table><tbody><tr>" + a[i] + "</tr></tbody></table>";
}
var div = document.createElement("div");
div.innerHTML = a[i]; /*这里就是修正的目的*/
/*如果是table等表格元素*/
if ( table ) {
div = div.firstChild;
if ( table != "thead" ) div = div.firstChild;
if ( table == "td" ) div = div.firstChild;
}
//将修正后的元素添加
for ( var j = 0; j < div.childNodes.length; j++ )
r.push( div.childNodes[j] );
} else if ( a[i].jquery || a[i].length && !a[i].nodeType )
for ( var k = 0; k < a[i].length; k++ )
r.push( a[i][k] );
else if ( a[i] !== null )
r.push( a[i].nodeType ? a[i] : document.createTextNode(a[i].toString()) );
}
return r;
},
这里clean函数还不是太懂。
get函数返回包装集的参数位置对应的值,当参数为空时,返回所有值
get: function( num ) {
// Watch for when an array (of elements) is passed in
if ( num && num.constructor == Array ) {
// Use a tricky hack to make the jQuery object
// look and feel like an array
this.length = 0;
/*将两个数组拼接,为什么要返回这样的数组?*/
[].push.apply( this, num );
return this;
} else
return num == undefined ?
// Return a 'clean' array
jQuery.map( this, function(a){ return a } ) :
// Return just the object
this[num];
},
还有所使用的each函数:
/*apply函数置换调用者的this变量*/
each: function( obj, fn, args ) {
if ( obj.length == undefined )
for ( var i in obj )
fn.apply( obj[i], args || [i, obj[i]] );/*args为fn的参数*/
else
for ( var i = 0; i < obj.length; i++ )
fn.apply( obj[i], args || [i, obj[i]] );
return obj;
},
这里转一下apply的调用:
比较下面两端代码
var obj={s:'obj'};
window.s="win";
function cat(a){
alert(this.s+a);
}
cat.apply(obj,'obj');
cat.apply(null,'obj');
apply的作用是修改函数(类)中的this的取值,在jquery源码中,这经常用到。因为this的取值可以修改这意义重大。