在网站的开发中,经常会自己写一些jQuery插件来方便使用,其中自然少不了一个关键的方法->jQuery.extend(),使用这个方法来扩展jQuery对象。
那么今天就来讲讲这个函数的实现原理。
这个方法不仅仅可以实现插件,当然也有它本来的功能,扩展对象。like this:
var person = {name:‘李四‘}; var person2 = $.extend(person,{age:20},{sex:‘male‘}); //person.name=‘李四‘; //person.age=20; //person.sex=‘male‘;person2与person扩展后是同一个对象
这个函数的第一个函数指的是要被扩充的对象(target),第二、第三个函数则是附加对象。通俗点将,jQuery将检查target中没有的属性,而在后面两个对象中却存在,那么这些属性将被添加到target中。
那么我们写插件又是怎么回事呢,我们只用了一个参数啊,像这样:
$.extend({ myExtendMethod:function(){ alert(‘这是我的方法‘); } });
像上面这个例子里,我们的$.extend方法中只有一个Object类型的参数,即:{myExtendMethod},那么这个时候怎么扩展,去扩展谁?target又是什么?当然要扩展的就是我们爱不释手的jQuery了!上一下源码:
1 jQuery.extend = jQuery.fn.extend = function() { 2 var options, name, src, copy, copyIsArray, clone, 3 target = arguments[0] || {}, 4 i = 1, 5 length = arguments.length, 6 deep = false; 7 8 // 不会满足,因为我们传进来的是Object 9 if ( typeof target === "boolean" ) { 10 deep = target; 11 target = arguments[1] || {}; 12 // skip the boolean and the target 13 i = 2; 14 } 15 16 // 同样不会满足 17 if ( typeof target !== "object" && !jQuery.isFunction(target) ) { 18 target = {}; 19 } 20 21 // length为1,i也为1,所以会走这个条件 22 if ( length === i ) { 23 target = this; 24 --i; 25 } 26 27 for ( ; i < length; i++ ) { 28 // Only deal with non-null/undefined values 29 if ( (options = arguments[ i ]) != null ) { 30 // Extend the base object 31 for ( name in options ) { 32 src = target[ name ]; 33 copy = options[ name ]; 34 35 // Prevent never-ending loop 36 if ( target === copy ) { 37 continue; 38 } 39 40 // Recurse if we‘re merging plain objects or arrays 41 if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { 42 if ( copyIsArray ) { 43 copyIsArray = false; 44 clone = src && jQuery.isArray(src) ? src : []; 45 46 } else { 47 clone = src && jQuery.isPlainObject(src) ? src : {}; 48 } 49 50 // Never move original objects, clone them 51 target[ name ] = jQuery.extend( deep, clone, copy ); 52 53 // Don‘t bring in undefined values 54 } else if ( copy !== undefined ) { 55 target[ name ] = copy; 56 } 57 } 58 } 59 } 60 61 // Return the modified object 62 return target; 63 };
通过这段代码可以看到第一行的定义,$.extend和$.fn.extend的定义方法为同一个匿名函数,也就是他们是一个方法实现的,只是扩展的对象前者是jQuery,
后者是jQuery.fn =jQuery.prototype也就是 jQuery实例( $(‘div‘) )。$.fn.extend()就是为jQuery添加实例方法。
ps:如果不了解js原型概念可以看我上一篇文章js创建对象,或者看其他园子的文章。
源码:jQuery.fn= jQuery.prototype
下面就来看看$.extend函数只有一个参数时怎么执行的。
看3行代码的target变量,指定了arguments[0]为它的值,按照刚刚我们定义的插件,就是{myExtendMethod:function(){...}}这个object;
继续往下看,看我21行的注释,this指的是jQuery对象,然后把jQuery赋给了target变量,并且把 i 变成了0 ;
然后进入for循环,在第55行代码的时候,会把我们的参数Object赋给jQuery对象,这样,就把myExtendMethod这个方法添加到jQuery对象上了。
1 $.extend({ 2 testMethod: function () { 3 alert(111); 4 } 5 }); 6 $.fn.extend({ 7 testMethod2: function () { 8 alert(222); 9 } 10 }); 11 //调用扩展方法 12 $.testMethod();//弹出111 13 $("#List1").testMethod2();//弹出222