jQuery源码分析-extend函数



Js代码   收藏代码
  1. /*! 
  2.  * jQuery源码分析-extend函数 
  3.  * jQuery版本:1.4.2 
  4.  *  
  5.  * ---------------------------------------------------------- 
  6.  * 函数介绍 
  7.  * jQuery.extend与jQuery.fn.extend指向同一个函数对象 
  8.  * jQuery.extend是jQuery的属性函数(静态方法) 
  9.  * jQuery.fn.extend是jQuery函数所构造对象的属性函数(对象方法) 
  10.  * 
  11.  * ---------------------------------------------------------- 
  12.  * 使用说明 
  13.  * extend函数根据参数和调用者实现功能如下: 
  14.  * 1.对象合并: 
  15.  * 对象合并不区分调用者,jQuery.extend与jQuery.fn.extend完全一致 
  16.  * 也就是说对jQuery对象本身及jQuery所构造的对象没有影响 
  17.  * 对象合并根据参数区分,参数中必须包括两个或两个以上对象 
  18.  * 如:$.extend({Object}, {Object}) 或 $.extend({Boolean},{Object}, {Object}) 
  19.  * 对象合并返回最终合并后的对象,支持深度拷贝 
  20.  *  
  21.  * 2.为jQuery对象本身增加方法: 
  22.  * 这种方式从调用者和参数进行区分 
  23.  * 形式为 $.extend({Object}) 
  24.  * 这种方式等同于 jQuery.{Fnction Name} 
  25.  *  
  26.  * 3.原型继承: 
  27.  * 原型继承方式可以为jQuery所构造的对象增加方法 
  28.  * 这种方式也通过调用者和参数进行区分 
  29.  * 形式为 $.fn.extend({Object}) 
  30.  * 这种方式实际上是将{Object}追加到jQuery.prototype,实现原型继承 
  31.  *  
  32.  * ---------------------------------------------------------- 
  33.  *  
  34.  */  
  35.    
  36. // jQuery.fn = jQuery.prototype  
  37. // jQuery.fn.extend = jQuery.prototype.extend  
  38. jQuery.extend = jQuery.fn.extend = function(){  
  39.   
  40.     //目标对象  
  41.     var target = arguments[0] || {},      
  42.       
  43.     //循环变量,它会在循环时指向需要复制的第一个对象的位置,默认为1  
  44.     //如果需要进行深度复制,则它指向的位置为2  
  45.     i = 1,      
  46.       
  47.     //实参长度  
  48.     length = arguments.length,      
  49.       
  50.     //是否进行深度拷贝  
  51.     //深度拷贝情况下,会对对象更深层次的属性对象进行合并和覆盖  
  52.     deep = false,      
  53.       
  54.     //用于在复制时记录参数对象  
  55.     options,      
  56.       
  57.     //用于在复制时记录对象属性名  
  58.     name,      
  59.       
  60.     //用于在复制时记录目标对象的属性值  
  61.     src,      
  62.       
  63.     //用于在复制时记录参数对象的属性值  
  64.     copy;  
  65.       
  66.     //只有当第一个实参为true时,即需要进行深度拷贝时,执行以下分支  
  67.     if (typeof target === "boolean") {  
  68.         //deep = true,进行深度拷贝  
  69.         deep = target;  
  70.           
  71.         //进行深度拷贝时目标对象为第二个实参,如果没有则默认为空对象  
  72.         target = arguments[1] || {};  
  73.           
  74.         //因为有了deep深度复制参数,因此i指向的位置为第二个参数  
  75.         i = 2;  
  76.     }  
  77.       
  78.     //当目标对象不是一个Object且不是一个Function时(函数也是对象,因此使用jQuery.isFunction进行检查)  
  79.     if (typeof target !== "object" && !jQuery.isFunction(target)) {  
  80.           
  81.         //设置目标为空对象  
  82.         target = {};  
  83.     }  
  84.       
  85.     //如果当前参数中只包含一个{Object}  
  86.     //如 $.extend({Object}) 或 $.extend({Boolean}, {Object})  
  87.     //则将该对象中的属性拷贝到当前jQuery对象或实例中  
  88.     //此情况下deep深度复制仍然有效  
  89.     if (length === i) {  
  90.           
  91.         //target = this;这句代码是整个extend函数的核心  
  92.         //在这里目标对象被更改,这里的this指向调用者  
  93.         //在 $.extend()方式中表示jQuery对象本身  
  94.         //在 $.fn.extend()方式中表示jQuery函数所构造的对象(即jQuery类的实例)  
  95.         target = this;  
  96.           
  97.         //自减1,便于在后面的拷贝循环中,可以指向需要复制的对象  
  98.         --i;  
  99.     }  
  100.       
  101.     //循环实参,循环从第1个参数开始,如果是深度复制,则从第2个参数开始  
  102.     for (; i < length; i++) {  
  103.           
  104.         //当前参数不为null,undefined,0,false,空字符串时  
  105.         //options表示当前参数对象  
  106.         if ((options = arguments[i]) != null) {  
  107.               
  108.             //遍历当前参数对象的属性,属性名记录到name  
  109.             for (name in options) {  
  110.                   
  111.                 //src用于记录目标对象中的当前属性值  
  112.                 src = target[name];  
  113.                   
  114.                 //copy用于记录参数对象中的当前属性值  
  115.                 copy = options[name];  
  116.                   
  117.                 //存在目标对象本身的引用,构成死循环,结束此次遍历  
  118.                 if (target === copy) {  
  119.                     continue;  
  120.                 }  
  121.                   
  122.                 //如果需要进行深度拷贝,且copy类型为对象或数组  
  123.                 if (deep && copy && (jQuery.isPlainObject(copy) || jQuery.isArray(copy))) {  
  124.                   
  125.                     //如果src类型为对象或数组,则clone记录src  
  126.                     //否则colne记录与copy类型一致的空值(空数组或空对象)  
  127.                     var clone = src && (jQuery.isPlainObject(src) || jQuery.isArray(src)) ? src : jQuery.isArray(copy) ? [] : {};  
  128.                       
  129.                     //对copy迭代深度复制  
  130.                     target[name] = jQuery.extend(deep, clone, copy);  
  131.                       
  132.                     //如果不需要进行深度拷贝  
  133.                 } else if (copy !== undefined) {  
  134.                       
  135.                     //直接将copy复制给目标对象  
  136.                     target[name] = copy;  
  137.                 }  
  138.             }  
  139.         }  
  140.     }  
  141.       
  142.     //返回处理后的目标对象  
  143.     return target;  
  144. };  
  145.   
  146.   
  147. /** 
  148.  * jQuery框架本身对extend函数的使用非常频繁 
  149.  * 典型示例为jQuery.ajax 
  150.  *  
  151.  */  
  152.   
  153. //使用extend对jQuery对象本身进行扩展,只给了一个参数对象  
  154. //该对象中的属性将被追加到jQuery对象中  
  155. jQuery.extend({  
  156.    
  157.     //jQuery.ajax  
  158.     //$.ajax  
  159.    
  160.     //这里的origSettings参数是自定义的ajax配置  
  161.     //jQuery对象本身有一个ajaxSettings属性,是默认的ajax配置  
  162.     ajax: function(origSettings){   
  163.    
  164.         //这里使用extend对ajax配置项进行合并  
  165.         //第一个参数表示进行深度拷贝  
  166.         //首先将第3个参数jQuery.ajaxSettings(即jQuery默认ajax配置)复制到第2个参数(一个空对象)  
  167.         //然后将第4个参数(自定义配置)复制到配置对象(覆盖默认配置)  
  168.         //这里的s就得到了最终的ajax配置项  
  169.         var s = jQuery.extend(true, {}, jQuery.ajaxSettings, origSettings);  
  170.     
  171.         //其它相关代码...(省略)  
  172.     }  
  173. });  





源码291~353行,jQuery.extend函数(utils)

jQuery.extend()使用方式有三种:
1.jQuery.extend({...}),参数为一个对象,这种使用方式是把参数的值cp给jQuery对象,这是扩展jQuery最常用的方式,后面很多代码都采用这种方式。
2.jQuery.extend({...},{...}...),参数为多个对象,这种方式是把后面的多个对象的值cp给第一个对象,如果后面对象有和前面对象相同的属性,则后面的覆盖前面的。
3.jQuery.extend(true,{a:{h:22,w:333}},{a:{h:552,s:2532},c:287}),深度cp,递归合并、覆盖、复制的方式。返回结果为{a:{h:552,w:333,s:2532},c:287}


接下来看源码:

Java代码   收藏代码
  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.     // Handle a deep copy situation  
  9.     //如果为深度复制,则目标对象和原对象游标值i,以及深度值都进行更新  
  10.     if ( typeof target === "boolean" ) {  
  11.         deep = target;  
  12.         target = arguments[1] || {};  
  13.         // skip the boolean and the target  
  14.         i = 2;  
  15.     }  
  16.   
  17.     // Handle case when target is a string or something (possible in deep copy)  
  18.     //当目标对象的值类型错误,则重置为{}  
  19.     if ( typeof target !== "object" && !jQuery.isFunction(target) ) {  
  20.         target = {};  
  21.     }  
  22.   
  23.     // extend jQuery itself if only one argument is passed  
  24.     //当参数值长度为1的情况下,目标对象就为jQuery自身  
  25.     if ( length === i ) {  
  26.         target = this;  
  27.         --i;  
  28.     }  
  29.   
  30.     for ( ; i < length; i++ ) {  
  31.         // Only deal with non-null/undefined values  
  32.         if ( (options = arguments[ i ]) != null ) {//忽略空对象  
  33.             // Extend the base object  
  34.             for ( name in options ) {  
  35.                 src = target[ name ];  
  36.                 copy = options[ name ];//存储对象的值  
  37.   
  38.                 // Prevent never-ending loop  
  39.                 if ( target === copy ) {  
  40.                     continue;  
  41.                 }  
  42.   
  43.                 // Recurse if we're merging plain objects or arrays  
  44.                   //深度复制只有属性深度多于俩层的对象关系的结构的,如{a:{s:21,age:11}}或{a:['s'=>21,'age'=>11]}  
  45.                 if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {  
  46.                     if ( copyIsArray ) {//如果是数组对象  
  47.                         copyIsArray = false;  
  48.                         clone = src && jQuery.isArray(src) ? src : [];  
  49.   
  50.                     } else {//普通对象  
  51.                         clone = src && jQuery.isPlainObject(src) ? src : {};  
  52.                     }  
  53.   
  54.                     // Never move original objects, clone them  
  55.                     // 调用自身进行递归复制  
  56.                     target[ name ] = jQuery.extend( deep, clone, copy );  
  57.   
  58.                 // Don't bring in undefined values  
  59.                 } else if ( copy !== undefined ) {//非深度CP直接覆盖目标属性  
  60.                     target[ name ] = copy;  
  61.                 }  
  62.             }  
  63.         }  
  64.     }  
  65.   
  66.     // Return the modified object  
  67.     return target;  
  68. }; 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值