您现在的位置:首页 >> 前端 >> 内容

createDelegate函数的委托代码实例

时间:2017/10/25 9:51:58 点击:

  核心提示: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');

Tags:CR RE EA AT 
作者:网络 来源:TOKYOQ