query扩展函数详解(我的人生颠覆)

来源:互联网 发布:程序员鼓励师图片 编辑:程序博客网 时间:2024/05/21 10:50

作者:zuoxiaolong8810(左潇龙),转载请注明出处。 http://blog.csdn.net/zuoxiaolong8810/article/details/8557817

          上次分析了jquery的源码,分享了jquery的核心框架架构,这一次我们抛开源码,只关注功能,来看一下jquery的扩展函数的使用到底有何神奇之处。

           为了看起来方便,我将所有的讲解都附在了代码中,这样看起来会更直观,由于我将多种测试放在一个页面当中,所以会有很多alert弹出,这里各位在测试的时候,可以将其中的功能分开来放,这样可以更加直观的看到效果。

           好了,现在就看一下jquery的扩展函数与我的人生吧。

[javascript] view plaincopy
  1. <html>  
  2. <head>  
  3. <script src="jquery-1.8.2.js" type="text/javascript"></script>  
  4. <script type="text/javascript">  
  5.     /* 
  6.      *jquery的extend方法的原版形式,jquery.extend(deep,target,source1,source2......)以及 
  7.      *jquery.fn.extend(deep,target,source1,source2......),下面分别演示两个函数的区别与相同之处。 
  8.      *参数详解: 
  9.      *deep:boolean类型,意为是否要深度拷贝 
  10.      *target:Object类型,意为要扩展的目标对象 
  11.      *source1:Object类型,意为被扩展的资源对象 
  12.      *source2....:与source1相同,理论上可以有无限个 
  13.     */  
  14.     //此处扩展的是$(即jQuery,以后都用$),当只有一个Object类型参数的时候,此方法扩展$。  
  15.     $.extend(  
  16.       {  
  17.         testExtend:function(){  
  18.             alert('extend success');  
  19.         }  
  20.       }  
  21.     );  
  22.     //此处扩展的是$()(即jQuery对象,以后都用$()),当只有一个Object类型参数的时候,此方法扩展$()。  
  23.     $.fn.extend(  
  24.       {  
  25.         testFnExtend:function(){  
  26.             alert('extend fn success');  
  27.         }  
  28.       }  
  29.     );  
  30.     //此处将成功弹出  
  31.     $.testExtend();  
  32.     //此处将报错,所以我们用try{}catch{}包围起来看错误信息,将提示错误。  
  33.     try{  
  34.         $("testDiv").testExtend();  
  35.     }catch(e){  
  36.         alert(e.toString());  
  37.     }  
  38.     //反过来也是一样,此处将成功弹出  
  39.     $("testDiv").testFnExtend();  
  40.     //此处将报错,所以我们用try{}catch{}包围起来看错误信息,将提示错误。  
  41.     try{  
  42.         $.testFnExtend();  
  43.     }catch(e){  
  44.         alert(e.toString());  
  45.     }  
  46.       
  47.     //下面将演示不扩展$或者$()的情况,即我们设定一个目标对象  
  48.       
  49.     var target = {};//目标对象  
  50.       
  51.     //此处target将作为目标对象扩展  
  52.     $.extend(target,  
  53.       {  
  54.         testExtend:function(){  
  55.             alert('extend success');  
  56.         }  
  57.       }  
  58.     );  
  59.     //扩展成功后,target具有testExtend方法  
  60.     target.testExtend();  
  61.       
  62.     //下面我们看下两个方法的作用是否相同  
  63.       
  64.     var targetFn = {};//目标对象  
  65.       
  66.     //此处targetFn将作为目标对象扩展  
  67.     $.fn.extend(targetFn,  
  68.       {  
  69.         testExtend:function(){  
  70.             alert('extend success');  
  71.         }  
  72.       }  
  73.     );  
  74.     //targetFn被成功扩展,扩展成功后,targetFn具有testExtend方法,说明指定了target,二者效果相同,用哪个都一样  
  75.     targetFn.testExtend();  
  76.       
  77.     /*最后我们来看下深度拷贝的含义,深度拷贝用文字来解释的意思是,当被扩展的属性如果也是一个对象的时候,那么也会 
  78.      *将该属性作为对象来扩展,而不会覆盖属性的对象中原有的属性。 
  79.      *这个文字解释略显苍白,我们来看一下实际的效果会如何。 
  80.     */  
  81.     //首先我们需要一个对象,这个对象的某一个属性又是一个对象。  
  82.       
  83.     //为了便于理解,这次我们采用现实当中的例子,我将为技术献身,以下纯属虚构。  
  84.     var me = {  
  85.         name:"zuoxiaolong",  
  86.         sex:"man",  
  87.         //注意,这里我的女朋友,我的属性,也是一个对象  
  88.         girlFriend:{  
  89.             name:"secret",  
  90.             sex:"woman"  
  91.         }  
  92.     };  
  93.       
  94.     //下面首先采用非深度拷贝的方式对我进行扩展,此处不再区分$.extend和$.fn.extend,因为二者在有目标对象的情况下,效果相同  
  95.     $.extend(me,  
  96.         {  
  97.             work:"programmer",//扩展我的工作为程序员  
  98.             girlFriend:{  
  99.                 work:"rich"//扩展我女朋友的职业为富婆,这是不是若干人群的梦想  
  100.             }  
  101.         }  
  102.     );  
  103.       
  104.     //我们来看下非深度拷贝,扩展以后的结果,我的生活会变成什么样子  
  105.     alert("name:" + me.name);  
  106.     alert("sex:" + me.sex);  
  107.     alert("work:" + me.work);  
  108.     //特别注意我的女朋友被扩展的结果  
  109.     alert("girlFriend.name:" + me.girlFriend.name);  
  110.     alert("girlFriend.sex:" + me.girlFriend.sex);  
  111.     alert("girlFriend.work:" + me.girlFriend.work);  
  112.     /* 
  113.      *是不是发现我女朋友的名字和性别都未知了,这是因为在非深度拷贝的情况下,如 
  114.      *果属性为对象,将会被扩展的属性值直接覆盖掉,也就是原来的属性name和sex会被直接覆盖,即name和sex会被work覆盖 
  115.      */  
  116.        
  117.     //我当然不能让我的生活如此悲催,一个连性别都不知道的富婆如何做我的女友,我们来看下神奇的深度拷贝  
  118.       
  119.     //这里我们需要重新定义me这个对象,因为之前已经被扩展了,这里要将我的生活重新来过  
  120.     me = {  
  121.         name:"zuoxiaolong",  
  122.         sex:"man",  
  123.         girlFriend:{  
  124.             name:"secret",  
  125.             sex:"woman"  
  126.         }  
  127.     };  
  128.     //注意,增加了第一个参数,deep为true,即深度拷贝  
  129.     $.extend(true,me,  
  130.         {  
  131.             work:"programmer",//依然扩展我的工作为程序员  
  132.             girlFriend:{  
  133.                 name:"chaolu",//当有相同属性名的时候会被覆盖  
  134.                 work:"manager"//当有多出的属性名的时候会被扩展,扩展我女朋友的职业为经理  
  135.             }  
  136.         }  
  137.     );  
  138.     //我们来重新查看一下扩展后的对象,看我的生活是否恢复正常  
  139.     alert("name:" + me.name);  
  140.     alert("sex:" + me.sex);  
  141.     alert("work:" + me.work);  
  142.     //特别注意我的女朋友被扩展的结果  
  143.     alert("girlFriend.name:" + me.girlFriend.name);  
  144.     alert("girlFriend.sex:" + me.girlFriend.sex);  
  145.     alert("girlFriend.work:" + me.girlFriend.work);  
  146.     //我的生活已经恢复正常,一切都完美了  
  147.       
  148.     //以上为属性为对象时的情况,那么当属性为数组时,则会以数组的下标进行覆盖和扩展  
  149.     //文字解释依旧苍白,我们来看例子,我将依然献身给技术  
  150.     me = {  
  151.         name:"zuoxiaolong",  
  152.         sex:"man",  
  153.         //这里注意,我的好朋友是一个数组  
  154.         goodFriends:["xubo","xiaochen","xiaoqiang"]  
  155.     };  
  156.       
  157.     //下面我们来看下深度拷贝对数组的影响  
  158.       
  159.     //第一个参数为true,深度拷贝  
  160.     $.extend(true,me,  
  161.         {  
  162.             work:"programmer",//依然扩展我的工作为程序员  
  163.             goodFriends:["shiqiang","andi","liulei"]  
  164.         }  
  165.     );  
  166.     //我的工作将被正常扩展  
  167.     alert("name:" + me.name);  
  168.     alert("sex:" + me.sex);  
  169.     alert("work:" + me.work);  
  170.     //主要关注我的好朋友的变化,这里或许有的人会以为在深度拷贝的情况下,我的好朋友将成为六个人,我们看结果  
  171.     alert("goodFriends:" + me.goodFriends);  
  172.       
  173.     //结果显示我原来的三个好朋友没有了,这里解释下为何在深度拷贝的情况下,会覆盖我原来的朋友,刚才我已经解释过  
  174.     //对数组的深度拷贝会以下标进行判断,所以说虽然是深度拷贝,但是后面扩展的goodFriends[0]和前面定义的goodFriends[0],将  
  175.     //会被认为是同一个属性名,所以依据同名替换的原理,这里我原来的朋友将会被替换。  
  176.       
  177.     //你或许会说,那能不能将六个人都扩展为我的好朋友。答案是否定的,这样直接扩展,无论如何,前三个位置都将会被扩展的头三个好朋友覆盖。  
  178.     //人生总是不完美的,有了新的好朋友,旧的朋友就容易被遗忘,但是只要你努力,你可以同时拥有,就像下面这样  
  179.     me = {  
  180.         name:"zuoxiaolong",  
  181.         sex:"man",  
  182.         //这里注意,我的好朋友是一个数组  
  183.         goodFriends:["xubo","xiaochen","xiaoqiang"]  
  184.     };  
  185.     var newGoodFriends = ["shiqiang","andi","liulei"];  
  186.     var nowGoodFriends = me.goodFriends.concat(newGoodFriends);//将原来的好朋友与新的好朋友努力连接在一起  
  187.       
  188.     //第一个参数取消,非深度拷贝,因为我们已经复制了前三个好朋友,虽然会被覆盖,但我们已经保存  
  189.     $.extend(true,me,  
  190.         {  
  191.             work:"programmer",//依然扩展我的工作为程序员  
  192.             goodFriends:nowGoodFriends  
  193.         }  
  194.     );  
  195.     //我的工作将被正常扩展  
  196.     alert("name:" + me.name);  
  197.     alert("sex:" + me.sex);  
  198.     alert("work:" + me.work);  
  199.     //再次关注我的好朋友的变化,我们看结果  
  200.     alert("goodFriends:" + me.goodFriends);  
  201.     //总结,人生有得到就有失去,但有些我们可以通过努力留住很多  
  202.       
  203.     //从以上结果我们可以看出,当属性为数组时,如果source属性中数组的长度大于target目标对象属性中数组的长度,那么无论是否深度拷贝,  
  204.     //都将彻底覆盖原有的数组元素,那么如果source属性中数组的长度小于target目标对象属性中数组的长度,是否深度拷贝是否会影响结果呢。  
  205.     //答案是肯定的,当出现上述情况时,如果非深度拷贝,将直接覆盖原有属性的数组,如果为深度拷贝,则会留下原有数组多出的元素。  
  206.     //下面看示例,依旧恢复我的生活  
  207.     me = {  
  208.         name:"zuoxiaolong",  
  209.         sex:"man",  
  210.         //这里注意,我的好朋友是一个数组  
  211.         goodFriends:["xubo","xiaochen","xiaoqiang"]  
  212.     };  
  213.     //注意,此处为非深度拷贝,这时将覆盖原有数组  
  214.     $.extend(me,  
  215.         {  
  216.             work:"programmer",//依然扩展我的工作为程序员  
  217.             goodFriends:["shiqiang","andi"]//此处注意,这里将要扩展的数组长度小于原来的长度  
  218.         }  
  219.     );  
  220.     //我的工作将被正常扩展  
  221.     alert("name:" + me.name);  
  222.     alert("sex:" + me.sex);  
  223.     alert("work:" + me.work);  
  224.     //再次关注我的好朋友的变化,我们看结果,是否会将原有的好朋友全部覆盖  
  225.     alert("goodFriends:" + me.goodFriends);  
  226.       
  227.     //结果显示,非深度拷贝,将直接覆盖原有的数组,我的好朋友开始减少,我们来看深度拷贝会出现什么情况  
  228.       
  229.     //依旧恢复我的生活  
  230.     me = {  
  231.         name:"zuoxiaolong",  
  232.         sex:"man",  
  233.         //这里注意,我的好朋友是一个数组  
  234.         goodFriends:["xubo","xiaochen","xiaoqiang"]  
  235.     };  
  236.     //注意,此处添加深度拷贝deep为true,这时将覆盖原有数组的相同部分,多余部分保存  
  237.     $.extend(true,me,  
  238.         {  
  239.             work:"programmer",//依然扩展我的工作为程序员  
  240.             goodFriends:["shiqiang","andi"]  
  241.         }  
  242.     );  
  243.     //我的工作将被正常扩展  
  244.     alert("name:" + me.name);  
  245.     alert("sex:" + me.sex);  
  246.     alert("work:" + me.work);  
  247.     //再次关注我的好朋友的变化,我们看结果,是否会留下多余的部分的好朋友,也就是这位叫"xiaoqiang"的朋友  
  248.     alert("goodFriends:" + me.goodFriends);  
  249.       
  250.     //从结果中看到,前两个好朋友被后面的扩展所替代,但是在深度拷贝下,最后的第三个好朋友将会被留存  
  251.     //从这里我们看出,当source属性中数组的长度小于target属性中数组的长度时,是否深度拷贝则会影响结果,反之则不会影响。  
  252. </script>  
  253. </head>  
  254. <body>  
  255.     <h2 id="testDiv">jquery extend test</h2>  
  256. </body>  
  257. </html>  

            jquery将我的人生颠覆好几次,我们总要来一下人生的总结,下面我们来整体的看一下这两个扩展函数:

             1.当第一个参数为boolean类型时,将指示是否深度拷贝。

             2.当参数中只有一个Objec类型的时候,$.extend扩展的是$,$.fn.extend扩展的是$()。

             3.当参数中有两个或两个以上的Object类型的时候,第一个Object类型的参数将作为target被扩展,而后面所有的Object类型的参数的属性都将被添加到target当中。
             总结下深度拷贝:

             1.当出现属性为对象时,如果选择深度拷贝,则会覆盖同名的属性,扩展多出的属性。否则,则直接覆盖整个对象。

             2.当出现属性为数组时,如果选择深度拷贝,则会覆盖同索引的属性,如果有多出的属性,则保留。否则,则直接覆盖整个数组。

0 0
原创粉丝点击