ECMAScript读Ext之三(原型伸张)

续上篇,

Ext.ns = Ext.namespace;  

有了一个简写的namespace。整个匿名函数执行完了。接下来

Ext.ns("Ext.util", "Ext.lib", "Ext.data");  
Ext.elCache = {};  

独家为Ext添加了util,lib,data,elCache属性,默许都是空的对象。

Ext.apply(Function.prototype, {
    createInterceptor : function(){
        // ...
    },
    createCallback : function(){
        // ...
    },
    createDelegate : function(){
        // ...
    },
    defer : function(){
        // ...
    }
});

 

Ext.apply在首先篇已经讲到,那里用来扩大Function,为其增添了多少个法子createInterceptor、createCallback、createDelegate、defer。
多多盛行的JS库都不可同日而语档次的“污染”了原生JS,最登峰造极的如Prototype ,Mootools 。JQuery则完全两样,一个匿名函数执行后便出生了集所有API为一身的强劲
$ .
即使如此,JQuery的事件目标则不是DOM中事件目的,它完全重写了一个包容IE,DOM3的轩然大波目的。那里的污染加了双引号,不赞成的就精通成伸张吧。

 

createInterceptor 方法

createInterceptor : function(fcn, scope){
    var method = this;
    return !Ext.isFunction(fcn) ?
            this :
            function() {
                var me = this,
                    args = arguments;
                fcn.target = me;
                fcn.method = method;
                return (fcn.apply(scope || me || window, args) !== false) ?
                        method.apply(me || window, args) :
                        null;
            };
},

Interceptor顾名思义,拦截器。它却不是Strust2中的拦截器,但仍然有部分相似之处。那里是选用所传函数fcn拦截,若是fcn重回false,将被堵住,true才执行。

var method =
this,因为是给Function.prototype伸张,由此其prototype上挂的兼具的函数,函数内的this都是Function,即函数自身。示例可能更便于掌握

Function.prototype.test = function(){
    alert(this);
};
function fn(){return 'test';}
fn.test();

给Function.prototype添加了一个test方法,定义函数fn,fn会自动再而三test方法,fn.test()时弹出的this可以看出就是fn自身。

!Ext.isFunction(fcn),那么些条件注明即使所传参数fcn不是一个function,那么将向来回到this,this即函数自身。或者说这时没有进行其余阻挡,原样重回了该函数自己。

当fcn为一个function时,将实施
“:”后的分支,此时给fcn添加了四个特性target,method。target是me,me是this。

那儿的this是什么样啊?多数景观下是window,但整整function如果作为对象属性存在时,this则是该目的。何人调用了createInterceptor,method就是哪个人。如:

function oldFn(){
    alert('test');
}
function ret(){
    return false;
}
var newFn = oldFn.createInterceptor(ret);
newFn();

oldFn继承了createInterceptor方法,且调用了它,参数是ret。那时createInterceptor内部的method,
fcn.method就是oldFn;me,fcn.target则为window对象。改成如下,me,fcn.target则为obj了。

 

function oldFn(){
    alert('test');
}
function ret(){
    return false;
}
var obj = {name:'jack'};
obj.method = oldFn.createInterceptor(ret);
obj.method();

 

再往下看
(fcn.apply(scope || me || window, args) !==
false),所传参数fcn被实践,执行上下文优先是scope,其次是me,最终是window。重临结果不等于false才实施method。method执行上下文先为me,me不存在则是window。

全副createInterceptor方法就看完了,上边是一个切实事例:

function sayName(name){
    alert('hello, ' + name);
}
function rule(name){
    return name == 'snandy';
}
var sayName2 = sayName.createInterceptor(rule);
sayName2('zhangsan'); // -> no alert
sayName2('snandy');   // -> "hello, snandy"

 

createCallback 方法

createCallback : function(/*args...*/){
    // make args available, in function below
    var args = arguments,
        method = this;
    return function() {
        return method.apply(window, args);
    };
},

本条点子丰盛有用,完结不难。重返一个新函数,新函数内进行method(method是何人就无须再提了吧),会把外围的参数给传进来。
初学者平日 纠结于给事件handler传参数 。createCallback
解决了给DOM事件handler(监听器)传参问题。
createCallback
不仅用在DOM事件handler上您一点一滴可以自定义事件,设计一套属于自己的 寓目者情势 API。即每个类有谈得来的事件,如 LTMaps ,除了具有属性,方法还有很多事变,如运动地图(move),缩放地图(zoom)。Ext的众多UI组件也都是那种情势,Ext.Panel 具有afterlayout,close等事件。

在给那几个事件添加hanlder,又想传参或许也会用到 createCallback。

再看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);
    };
},

createDelegate 比 createCallback
更强硬,除了能缓解回调函数传参问题。还是能决定:
1,
自定义参数是还是不是覆盖默许参数(如 DOM事件目的 作为handler第二个参数)
2, 自定义参数的职位

里头贯彻:取我(var
method=this),再次回到一个新function,该function调用自身(method.apply),同时指定上下文(obj||window)及参数(callArgs)。就这么不难,细节之处在于对参数的主宰。

1,只传obj和args时将覆盖回调函数默许参数(DOM事件目的)

<a href="#" id="aa">SINA</a>
<script type="text/javascript">
    var aa = document.getElementById('aa');
    function sayName(name){
        alert('hello, ' + name);
    }
    var sayName2 = sayName.createDelegate(aa,['jack']);
    aa.onclick = sayName2;
</script>

 

2,三个参数都传,appendArgs为true时,默许参数(DOM事件目的)地方不变(第四个),自定义参数args在最后

<a href="#" id="aa">SINA</a>
<script type="text/javascript">
    var aa = document.getElementById('aa');
    function sayName(){     
        alert('实际参数长度:' + arguments.length);
        alert('hello, ' + arguments[0]);
        alert('hi, ' + arguments[1]);
    }
    var sayName2 = sayName.createDelegate(aa,['jack'],true);
    aa.onclick = sayName2;
</script>

 

3, 多少个参数都传,appendArgs为数字时将指定自定义参数的地方

<a href="#" id="aa">SINA</a>
<script type="text/javascript">
    var aa = document.getElementById('aa');
    function sayName(name){     
        alert('实际参数长度:' + arguments.length);
        alert('hello, ' + arguments[0]);
        alert('hi, '+ arguments[1]);
        alert('hi, '+ arguments[2]);
    }
    var sayName2 = sayName.createDelegate(aa,['jack','lily'],0);
    aa.onclick = sayName2;
</script>

 

此外,method的施行上下文应该扩充this,那样实用一些了。

return method.apply(obj || this || window, callArgs);

 

接着看defer,指定函数在稍微微秒后进行

defer : function(millis, obj, args, appendArgs){
    var fn = this.createDelegate(obj, args, appendArgs);
    if(millis > 0){
        return setTimeout(fn, millis);
    }
    fn();
    return 0;
}

里面实用了刚刚提到的createDelegate方法,指定函数的实施上下文及参数设定。倘诺millis是正数则推迟执行回来set提姆eout的再次回到值(一个数字),有必不可少可用clearTimeout终止。否则马上施行,再次回到0。

 

好了,以上是对Function.prototype的恢弘。接下来是对String,Array的恢弘。使用Ext.applyIf,第一篇 已提到Ext.applyIf不会覆盖已有的艺术。

Ext.applyIf(String, {
    format : function(format){
        var args = Ext.toArray(arguments, 1);
        return format.replace(/\{(\d+)\}/g, function(m, i){
            return args[i];
        });
    }
});

 

给String添加静态方法(类措施)format,可以把字符串中独特写法({0},{1})用指定的变量替换。如

var href = 'http://www.sina.com.cn', text = '新浪';
var s = String.format('<a href="{0}">{1}</a>', href, text);
alert(s); // --> <a href="http://www.sina.com.cn">新浪</a>

多少类似于JSP的EL表达式。

 

Array扩展,

Ext.applyIf(Array.prototype, {
    indexOf : function(o, from){
        var len = this.length;
        from = from || 0;
        from += (from < 0) ? len : 0;
        for (; from < len; ++from){
            if(this[from] === o){
                return from;
            }
        }
        return -1;
    },
    remove : function(o){
        var index = this.indexOf(o);
        if(index != -1){
            this.splice(index, 1);
        }
        return this;
    }
});

 

indexOf
再了然可是了呢,String早有了。用来探寻元素是或不是在数组中,若是有则赶回该因素在数组中的索引,否则重回-1。该方法在 ECMAScript
5
 中已经引入,各浏览器的新本子都落到实处了。

reomve 删除指定元素,如若存在该因素则删除,重返数组自身。

 

好了,以上3篇是百分之百Ext-core的Ext.js。