核心提示:createDelegate函数createDelegate是Function的扩展,无论是网上还是书上对它的评价都很高。今天特地拿出来分析一番。Ext源码分析与开发实例宝典 的例子p1/pp2/pp...
createDelegate函数
createDelegate是Function的扩展,无论是网上还是书上对它的评价都很高。今天特地拿出来分析一番。
Ext源码分析与开发实例宝典 的例子
<p>1</p> <p>2</p> <p>3</p>
function addEvent(el,type,fn){ if(el.addEventlistener)el.addEventListener(type,fn,false); if(el.attachEvent)el.attachEvent('on'+type,fn); } var doms = document.getElementsByTagName('p'); var length=doms.length; for(var i=0;i
在上边的例子中 期望点击不同的p 弹出相应的下标值,但是实际情况是 弹出的值全部都是3
因为 每次循环闭包中callback函数的函数体都会变化,而事件注册的都是这个函数的引用。所以循环结束i定格在3上。
这种错误很常见 解决办法就是 声明一个可以储存每次传入的值函数
var delegate=function(m){return function(){ alert(m)} }
由此可见仅仅在函数外层包裹一层函数就ok了。
一般来说代理函数的作用如下:
改变函数作用域
改变函数参数形式
改变函数内容
Ext3.0 createDelegate 源码:
createDelegate : function(obj, args, appendArgs){ var method = this; return function() { var callArgs = args || arguments; if (appendArgs === true){ callArgs = Array.prototype.slice.call(arguments, 0); callArgs = callArgs.concat(args); }else if (Ext.isNumber(appendArgs)){ callArgs = Array.prototype.slice.call(arguments, 0); // copy arguments first var applyArgs = [appendArgs, 0].concat(args); // create method call params Array.prototype.splice.apply(callArgs, applyArgs); // splice them in } return method.apply(obj || window, callArgs); }; }
var applyArgs = [appendArgs, 0].concat(args); //得到一个[n,0,...]的形式 Array.prototype.splice.apply(callArgs, applyArgs); //splice(索引位置,删除的元素个数,添加的值。。。。);
首先这是一个典型的闭包 在调用createDelegate的后。 返回的函数中隐藏有被委托函数的引用 method,提前传入的参数数组args 和配置项appendArgs。作用域obj
在被委托函数调用后 根据实际传参arguments 以及之前的参数生成真正参数列表 在作用域obj下执行..
完整测试代码:
function isNum(v){ return !!v || Object.prototype.toString.call(v)==='[object Number]' } console.log(isNum(3)) Function.prototype.createDelegate=function(obj, args, appendArgs){ var method = this; return function() { var callArgs = args || arguments; if (appendArgs === true){ callArgs = Array.prototype.slice.call(arguments, 0); callArgs = callArgs.concat(args); }else if (isNum(appendArgs)){ callArgs = Array.prototype.slice.call(arguments, 0); // copy arguments first var applyArgs = [appendArgs, 0].concat(args); // create method call params Array.prototype.splice.apply(callArgs, applyArgs); // splice them in } return method.apply(obj || window, callArgs); }; } function test(){ for(var i =0 ; i<arguments.length;i++){ console.log(arguments[i]); } } var M = new Object(); M.test=test.createDelegate(this,['a','b','c'],true); M.test('d','e','f'); console.log('test2------------'); M.test2=test.createDelegate(this,['a','b','c'],1); M.test2('d','e','f');