jquery提供了两个插件接口,一个是jquery.extend,另一个是jquery.fn.extend。(在jquery源码中jquery代表的是全局对象,而jquery.fn = jquery.prototype也就是jquery的原型对象)所以可以这样理解在使用jquery.extend来扩展插件的时候其实是在jquery的命名空间也就是jquery对象本身来扩展。而使用jquery.fn.extend来扩展插件的时候可以理解为在jquery的原型对象也就是jquery.prototype所代表的对象进行的扩展。又因为类的所有实例对象继承自同一个原型对象所以在这里我们可以认为在jquery.prototype上进行扩展其实就是为它的实例对象来添加方法。下面看看jquery中源代码的写法:代码部分的大部分注释引用自http://www.cnblogs.com/aaronjs/p/3278578.html
jQuery.extend = jQuery.fn.extend = function() {
var src, copyIsArray, copy, name, options, clone, target = arguments[0] || {}, // 常见用法 jQuery.extend( obj1, obj2 ),此时,target为arguments[0] i = 1, length = arguments.length, deep = false; // Handle a deep copy situation if ( typeof target === "boolean" ) { // 如果第一个参数为true,即 jQuery.extend( true, obj1, obj2 ); 的情况 deep = target; // 此时target是true target = arguments[1] || {}; // target改为 obj1 // skip the boolean and the target i = 2; } // Handle case when target is a string or something (possible in deep copy) if ( typeof target !== "object" && !jQuery.isFunction(target) ) { // 处理奇怪的情况,比如 jQuery.extend( 'hello' , {nick: 'casper})~~ target = {}; } // extend jQuery itself if only one argument is passed if ( length === i ) { // 处理这种情况 jQuery.extend(obj),或 jQuery.fn.extend( obj ) target = this; // jQuery.extend时,this指的是jQuery;jQuery.fn.extend时,this指的是jQuery.fn --i; } for ( ; i < length; i++ ) { // Only deal with non-null/undefined values if ( (options = arguments[ i ]) != null ) { // 比如 jQuery.extend( obj1, obj2, obj3, ojb4 ),options则为 obj2、obj3... // Extend the base object for ( name in options ) { src = target[ name ]; copy = options[ name ]; // Prevent never-ending loop if ( target === copy ) { // 防止自引用,这个意思是防止copy就是target本身例如:var test = {init:function(){return this;}} 那么如果调用test.init()这是一个死循环。 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 { 被拷贝的属性值是个plainObject,比如{ nick: 'casper' } 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 ) { // 浅拷贝,且属性值不为undefined target[ name ] = copy; } } } } // Return the modified object return target;};