将jQuery源码简化后,留下jQuery对象构建的主要部分如下所示(如果有些看不懂,可以使用火狐的js调试器单步跟踪整个过程,可以看看jQuery对象下的方法和jQuery.prototype(火狐调试器下是_proto_)下的方法的变化):如有不对的地方,请指正,代码是从jquery-1.7.1.js中拷贝过来的。
//最外层是一个自执行函数,即可以起到闭包的作用,又可以起到初始化执行的作用
(function( window, undefined ) {
//将jQuery的构建放到闭包中,可以将jQuery的构建过程与外界隔离开
var jQuery = (function() {
var jQuery = function( selector, context ) {
//此处构建jQuery对象,构造函数构造的对象(即this)将被抛弃。
//因为jQuery.fn.init.prototype = jQuery.fn = jQuery.prototype
//所以返回的对象将继承自jQuery.prototype,即可以继承jQuery.prototype中定义的方法和属性
return new jQuery.fn.init( selector, context, rootjQuery );
};
//为什么要定义jQuery.fn?我目前的分析是为了扩展jQuery.prototype,
//取个fn的名称比直接用jQuery.prototype更易于理解
jQuery.fn = jQuery.prototype = {
constructor: jQuery,
init: function( selector, context, rootjQuery ) {
//返回一个类数组对象
},
size: function() {
return this.length;
},
each: function( callback, args ) {
return jQuery.each( this, callback, args );
}
//中间省略很多定义在原型中的方法
};
//联系上面的jQuery.fn = jQuery.prototype,是不是就有
//jQuery.fn.init.prototype = jQuery.fn = jQuery.prototype了呢。。。
//jQuery.fn.init.prototype = jQuery.prototype 的作用是:
//初始化jQuery对象是调用的jQuery.fn.init构造函数,该构造函数构造的对象的prototype指向jQuery.prototype
jQuery.fn.init.prototype = jQuery.fn;
//此处为定义扩展jQuery的方法。通过jQuery.extend
jQuery.extend = jQuery.fn.extend = function() {
var target = arguments[0] || {},
i = 1,
length = arguments.length;
// extend jQuery itself if only one argument is passed
//上面的意思是:如果只有一个参数传进来,就是扩展jQuery自身。
//至于是扩展jQuery的静态方法还是扩展jQuery的原型方法,就要看调用者了,即这里的this
//如果是通过jQuery.extend调用的,则this指向jQuery;
//如果通过jQuery.fn.extend调用的,则this指向jQuery.prototype,因为jQuery.fn = jQuery.prototype
if ( length === i ) {
target = this;
--i;
}
//此处删减部分代码
for ( ; i < length; i++ ) {
// Only deal with non-null/undefined values
if ( (options = arguments[ i ]) != null ) {
// Extend the base object
for ( name in options ) {
src = target[ name ];
copy = options[ name ];
// Prevent never-ending loop
if ( target === copy ) {
continue;
}
// Recurse if we're merging plain objects or arrays
if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
if ( copyIsArray ) {
copyIsArray = false;
clone = src && jQuery.isArray(src) ? src : [];
} else {
clone = src && jQuery.isPlainObject(src) ? src : {};
}
// Never move original objects, clone them
target[ name ] = jQuery.extend( deep, clone, copy );
// Don't bring in undefined values
} else if ( copy !== undefined ) {
//此处为扩展jQuery静态方法和jQuery原型方法最重要的一步。
//当使用jQuery.extend({})时,是扩展jQuery静态方法;当使用jQuery.fn.extend({})时,是扩展jQuery的原型方法
//因为使用jQuery.extend时,target=jQuery;当使用jQuery.fn.extend时,因为jQuery.fn=jQuery.prototype,所以target=jQuery.prototype
target[ name ] = copy;
}
}
}
}
// Return the modified object
return target;
};
//此处代码执行后,将如下的noConflict、trim方法扩展为了jQuery的静态方法。参见jQuery.extend函数的定义
//单步跟踪完这个方法后,将发现jQuery下多了noConflict、trim等方法(其它更多的方法在此处被删除了)。
jQuery.extend({
noConflict: function( deep ) {
if ( window.$ === jQuery ) {
window.$ = _$;
}
if ( deep && window.jQuery === jQuery ) {
window.jQuery = _jQuery;
}
return jQuery;
},
// Use native String.trim function wherever possible
trim: trim ?
function( text ) {
return text == null ?
"" :
trim.call( text );
} :
// Otherwise use our own trimming functionality
function( text ) {
return text == null ?
"" :
text.toString().replace( trimLeft, "" ).replace( trimRight, "" );
}
});
// All jQuery objects should point back to these
rootjQuery = jQuery(document);
//到此处为止,jQuery对象构建完毕,但后面还可以通过jQuery.extend和jQuery.fn.extend对jQuery进行扩展
return jQuery;
})();
//将jQuery挂到window对象上
window.jQuery = window.$ = jQuery;
})( window );