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

 

posted @ 2014-01-03 17:39  {前端开发}  阅读(401)  评论(0编辑  收藏  举报