• js中call与apply用法


      1 call和apply,它们的作用都是将函数绑定到另外一个对象上去运行
      2 两者的格式和参数定义:
      3 call( thisArg [,arg1,arg2,… ] );       // 参数列表,arg1,arg2,...
      4 apply(thisArg [,argArray] );                 // 参数数组,argArray
      5 上面两个函数内部的this指针,都会被赋值为thisArg,这可实现将函数作为另外一个对象的方法运行的目的
      6 
      7 一、call 的简单用法
      8 首先,我们先看个简单的例子(call):
      9 [html] view plaincopyprint?
     10 <!doctype html>  
     11   
     12 <html>  
     13     <head>  
     14         <title> call-apply </title>  
     15     </head>  
     16   
     17     <body>  
     18         <input type="text" id="idTxt" value="input text">  
     19           
     20         <script type="text/javascript">  
     21             var value = "global var";  
     22               
     23             function mFunc()  
     24             {  
     25                 this.value = "member var";  
     26             }  
     27               
     28             function gFunc()  
     29             {  
     30                 alert(this.value);  
     31             }         
     32                                                       
     33             window.gFunc();                                 // show gFunc, global var  
     34             gFunc.call(window);                             // show gFunc, global var  
     35             gFunc.call(new mFunc());                        // show mFunc, member var  
     36             gFunc.call(document.getElementById('idTxt'));   // show element, input text  
     37         </script>  
     38           
     39         <script language="javascript">  
     40             var func = new function()  
     41             {  
     42                 this.a = "func";  
     43             }  
     44               
     45             var func2 = function(x)  
     46             {  
     47                 var a = "func2";  
     48                 alert(this.a);                
     49                 alert(x);  
     50             }  
     51               
     52             func2.call(func, "func2");                      // show func and func2  
     53         </script>  
     54     </body>  
     55 </html>  
     56 然后,运行结果如下:
     57 global var
     58 global var
     59 member var
     60 input text
     61 func
     62 func2
     63 测试环境:Google Chrome 10.0.648.45
     64 最后,分析结果
     65 1、全局对象window调用函数gFunc,this指向window对象,因此this.value为global var
     66 2、函数gFunc调用call方法,this默认指向第一个参数window对象,因此this.value也为global var
     67 3、函数gFunc调用call方法,this默认指向第一个参数new mFunc(),即mFunc的对象,因此this.value为mFunc的成员变量member var
     68 4、函数gFunc调用call方法,this默认指向第一个参数input text控件,即id=‘idTxt’的控件,因此this.value为input控件的value值input text
     69 5、函数func2调用call方法,this默认指向第一个参数func函数对象,因此this.value为this.a,即func
     70 6、函数func2调用call方法,第二个参数属于函数对象func2的参数,因此alert(x)为第二个参数func2
     71 
     72 二、call 继承用法与改进
     73 js使用call模拟继承
     74 测试代码:
     75 [html] view plaincopyprint?
     76 <!doctype html>  
     77   
     78 <html>  
     79     <head>  
     80         <title> call - apply for inherit </title>  
     81     </head>  
     82       
     83     <body>  
     84         <script type="text/javascript">  
     85             function baseA()        // base Class A  
     86             {  
     87                 this.member = "baseA member";  
     88                 this.showSelfA = function()  
     89                 {  
     90                     window.alert(this.member);  
     91                 }  
     92             }  
     93               
     94             function baseB()        // base Class B  
     95             {  
     96                 this.member = "baseB member";  
     97                 this.showSelfB = function()  
     98                 {  
     99                     window.alert(this.member);  
    100                 }  
    101             }  
    102               
    103             function extendAB()     // Inherit Class from A and B  
    104             {  
    105                 baseA.call(this);   // call for A  
    106                 baseB.call(this);   // call for B  
    107             }  
    108               
    109             window.onload = function()  
    110             {  
    111                 var extend = new extendAB();      
    112                 extend.showSelfA();     // show A  
    113                 extend.showSelfB();     // show B  
    114             }  
    115         </script>  
    116     </body>  
    117 </html>  
    118 运行结果如下:
    119 baseB member
    120 baseB member
    121 测试环境:Google Chrome 10.0.648.45
    122 结果分析:
    123 预期的结果,应该是输出 baseA member 和 baseB member,但实际输出却是 baseB member 和 baseB member
    124 (已在IE9、86,Maxthon、Chrome、FF、Opera、Safari、360等浏览器测试过,结果都是后者:baseB member)
    125 至此,机器是不会错的,这就需要我们深入分析
    126 我们可能会很容易想到是this引起的,this两次都指向了baseB对象,但是推测真是这样吗?
    127 为了探究实质,我们借助chrome浏览器的调试工具,下断点,进行调试,结果发现:
    128 
    129 当调用extend.showSelfA();时,此时的this指向extendAB(并不是我们推测的两次都指向baseB对象)
    130 真实原因是extendAB对象的成员变量member在被baseB.call(this);实例化时,被baseB的成员member覆盖了,即extendAB的成员member由baseA member赋值成了baseB member
    131 当然,我们也可以对上面baseA代码稍作修改,来验证我们调试分析的正确性:
    132             function baseA()        // base Class A
    133             {
    134                 this.memberA = "baseA member";   // member改成memberA,以区分baseB中的member
    135                 this.showSelfA = function()
    136                 {
    137                     window.alert(this.memberA);    // 显示memberA
    138                 }
    139             }
    140 再次运行chrome等浏览器,结果如下:
    141 baseA  member
    142 baseB member
    143 结果和我们的预期相同,同时chrome调试信息也验证了我们的正确性:
    144 
    145 
    146 
    147 继承改进(prototype)
    148 以上模拟继承方法,仔细分析不是最好的。
    149 因为每次在函数(类)中定义了成员方法,都会导致实例有副本,因此可以借助prototype原型,进行改进
    150 改进举例如下:
    151 [html] view plaincopyprint?
    152 <!doctype html>  
    153   
    154 <html>  
    155     <head>  
    156         <title> call - apply for prototype </title>  
    157     </head>  
    158       
    159     <body>  
    160         <script type="text/javascript">  
    161             var Class = {  
    162                 create: function()              // create Function  
    163                 {  
    164                     return function()  
    165                     {  
    166                         this.initialize.apply(this, arguments);  
    167                     }  
    168                 }  
    169             };  
    170               
    171             var Person = Class.create();        // Create Class Person  
    172             Person.prototype = {                // prototype initialize  
    173                 initialize: function(obj1, obj2)  
    174                 {  
    175                     this.obj1 = obj1;  
    176                     this.obj2 = obj2;  
    177                 },  
    178                 showSelf: function()  
    179                 {  
    180                     alert("obj: " + this.obj1 + " and " + this.obj2);  
    181                 }  
    182             }  
    183               
    184             // instance Class  
    185             var person = new Person("man", "women");    // two params  
    186             person.showSelf();                          // show person  
    187         </script>  
    188     </body>  
    189 </html>  
    190 运行结果如下:
    191 obj: man and women
  • 相关阅读:
    DirectoryEntry配置IIS7出现ADSI Error:未知错误(0x80005000) [转]
    自定义Microsoft Visual Studio 代码模板,增加公司和个人信息
    RabbitMQ消息队列名词解释[转]
    RabbitMQ消息队列的小伙伴: ProtoBuf(Google Protocol Buffer) [转]
    RabbitMQ消息队列(七):适用于云计算集群的远程调用(RPC) [转]
    RabbitMQ消息队列(六):使用主题进行消息分发[转]
    RabbitMQ消息队列(五):Routing 消息路由 2[原]
    RabbitMQ消息队列(五):Routing 消息路由[转]
    RabbitMQ消息队列(四):分发到多Consumer(Publish/Subscribe)[转]
    RabbitMQ消息队列(三):任务分发机制[转]
  • 原文地址:https://www.cnblogs.com/chris-oil/p/3504077.html
Copyright © 2020-2023  润新知