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、8、6,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