Ext2.0中的createDelegate方法.
项目中经常使用createDelegate()方法来创建代理函数,从而改变当前函数中this的作用域.看下了源码,发现是通过js中的apply()方法来实现,想想也只能通过apply()或者call()方法来实现,因为js中只有这2个方法提供了改变当前函数内部this作用域的功能.此外,Ext中很多地方用到了call()和apply()方法,要想看懂源码,则必须先搞清这2个方法的用法.
createDelegate方法声明为:
1
createDelegate :
function
(obj, args, appendArgs)
{
2 var method = this;
3 return function() {
4 var callArgs = args || arguments;
5 if(appendArgs === true){
6 callArgs = Array.prototype.slice.call(arguments, 0);
7 callArgs = callArgs.concat(args);
8 }else if(typeof appendArgs == "number"){
9 callArgs = Array.prototype.slice.call(arguments, 0); // copy arguments first
10 var applyArgs = [appendArgs, 0].concat(args); // create method call params
11 Array.prototype.splice.apply(callArgs, applyArgs); // splice them in
12 }
13 return method.apply(obj || window, callArgs);
14 };
15 } ,
其中obj表示函数内部this作用域的范围,args是数组,appendArgs是"Boolean或Number",如果appendArgs是Boolean型的且值为true,那么args参数将跟在调用代理方法时传入的参数后面组成数组一起传入当前方法,否则只传入args,如果appendArgs为Number型,那么args将插入到appendArgs指定的位置.
2 var method = this;
3 return function() {
4 var callArgs = args || arguments;
5 if(appendArgs === true){
6 callArgs = Array.prototype.slice.call(arguments, 0);
7 callArgs = callArgs.concat(args);
8 }else if(typeof appendArgs == "number"){
9 callArgs = Array.prototype.slice.call(arguments, 0); // copy arguments first
10 var applyArgs = [appendArgs, 0].concat(args); // create method call params
11 Array.prototype.splice.apply(callArgs, applyArgs); // splice them in
12 }
13 return method.apply(obj || window, callArgs);
14 };
15 } ,
注意点:
1.函数内部的arguments关键字是函数执行时动态创建的,用来存储调用函数时所传入参数.这里第4行的arguments 并不指调用createDelegate方法所传入的参数(obj,args,appendArgs),而是指调用return function()时所传入的参数,即调用代理函数时所传入的参数.而args和appendArgs就是调用createDelegate方法时所传入的参数.总的来说,函数是在定义它的作用域中执行,而不是在调用它的作用域中执行.但也有特殊,比如这里的arguments.
2.call和apply的区别.
二者的第一个参数都是函数内部this的作用域,call的参数只能作为一串参数传入,而apply可以传入数组或arguments对象.如
fun.call(window,args0,args1,.....);
fun.apply(window,[1,2,3]);
但要注意的是apply方法传递到函数内部的参数实际也是作为一个个参数传递的.如果在fun内部测试arguments.length的话,则长度为3.同样,我们可以采用arguments[0],arguments[1],arguments[2]来分别引用1,2,3三个参数,而不是用arguments[0][0],arguments[0][1],arguments[0][2]来引用3个参数.这样才能解释11行的代码.