Ext3.1-createDelegate函数的委托

createDelegate函数

createDelegate是Function的扩展,无论是网上还是书上对它的评价都很高。今天特地拿出来分析一番。

Ext源码分析与开发实例宝典 的例子

<div>1</div>
<div>2</div>
<div>3</div>
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('div');
var length=doms.length;
for(var i=0;i<length,i++){
    var msg = 'you click '+i;
    var callback = function(){alert(msg);}
    addEvent(doms[i],'click',callback);
}

在上边的例子中 期望点击不同的div 弹出相应的下标值,但是实际情况是 弹出的值全部都是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');
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值