ExtJs源码分析与学习—ExtJs核心代码(三)

Ext为javascript的一些对象进行了扩展,主要有String、Array和Function,以下只介绍Ext.js中提到的方法,其他的后续再介绍

 

Ext为String扩展了方法 format,该方法为String的静态方法(类方法),可以把字符串中特殊写法({0},{1})用指定的变量替换

 

Js代码   收藏代码
  1. //定义带标记的字符串,并用传入的字符替换标记。每个标记必须是唯一的,而且必须要像{0},{1}...{n}  
  2.  //这样地自增长。  
  3.  //var cls = 'my-class', text = 'Some text';  
  4.  //var s = String.format('{0} '  '{1}', cls, text);  
  5.     //s现在是字符串:s now contains the string: 'my-class'   'Some text'  
  6.   
  7.     format : function(format){  
  8.         var args = Ext.toArray(arguments, 1);  
  9.         return format.replace(/\{(\d+)\}/g, function(m, i){  
  10.             return args[i];  
  11.         });  
  12.     }  

 
 Ext为Array扩展了方法 indexOf 和remove,这两个方法分别实现了索引和根据子元素删除对应的该元素

Js代码   收藏代码
  1. Ext.applyIf(Array.prototype, {  
  2.     /** 
  3.      * Checks whether or not the specified object exists in the array. 
  4.      * @param {Object} o The object to check for 
  5.      * @param {Number} from (Optional) The index at which to begin the search 
  6.      * @return {Number} The index of o in the array (or -1 if it is not found) 
  7.      */  
  8.     indexOf : function(o, from){  
  9.         var len = this.length;  
  10.         from = from || 0;  
  11.         from += (from < 0) ? len : 0;  
  12.         for (; from < len; ++from){  
  13.             if(this[from] === o){  
  14.                 return from;  
  15.             }  
  16.         }  
  17.         return -1;  
  18.     },  
  19.   
  20.     /** 
  21.      * Removes the specified object from the array.  If the object is not found nothing happens. 
  22.      * @param {Object} o The object to remove 
  23.      * @return {Array} this array 
  24.      */  
  25.     remove : function(o){  
  26.         var index = this.indexOf(o);  
  27.         if(index != -1){  
  28.             this.splice(index, 1);  
  29.         }  
  30.         return this;  
  31.     }  
  32. });  

 

编者在实际开发中经常会用到以下两个方法,也很实用

 

Js代码   收藏代码
  1. /** 
  2.   * 数组插入元素 
  3.   * @param {} index 插入位置 
  4.   * @param {} o 插入元素 
  5.   * @return {} 
  6.   */  
  7.  insert : function (index,o){  
  8.   if(index <= 0){  
  9.             return this.unshift(o);//插入到首元素  
  10.         }  
  11.         if(index >= this.length){  
  12.             return this.push(o);//插入到末元素  
  13.         }  
  14.         var sub = this.slice(index, this.length);  
  15.         this.length = index;  
  16.         this.push(o);  
  17.         for(var i = 0; i < sub.length; i++){  
  18.          this.push(sub[i]);  
  19.         }  
  20.         return this;  
  21.  },  
  22.    
  23.  /** 
  24.   * 删除数组中指定的元素 
  25.   * @param {} index 
  26.   * @return {} 
  27.   */  
  28.  removeAt : function(index){  
  29.         if(index != -1){  
  30.             this.splice(index, 1);  
  31.         }  
  32.         return this;  
  33.     }  

 

以下扩展String方法也很有用

Js代码   收藏代码
  1. Ext.applyIf(String,{  
  2.    
  3.  /** 
  4.   * 把驼峰格式的字符串转换为-格式 
  5.   * alert(<span style="font-family: Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', Consolas, 'Courier New', monospace; line-height: 18px; white-space: normal;">humpToConnector</span>('aaaBbbCcc','-')); //return aaa-bbb-ccc 
  6.   * @param {} str 
  7.   * @param {} conj 
  8.   * @return {} 
  9.   */  
  10.     humpToConnector : function(str, conj){  
  11.   //str = !str ? str : String(str);  
  12.   var index = str.search(/[A-Z]/);  
  13.   if (index >= 0) {  
  14.    var c = str.charAt(index);  
  15.    return String.humpToConnector(str.substring(0, index) + conj  
  16.        + c.toLowerCase() + str.substring(index + 1), conj);  
  17.   } else {  
  18.    return str;  
  19.   }  
  20.  }  
  21. });  

 

Ext对Function的扩展

 

createInterceptor方法

Js代码   收藏代码
  1. createInterceptor : function(fcn, scope){  
  2.         var method = this;  
  3.         return !Ext.isFunction(fcn) ?  
  4.                 this :  
  5.                 function() {  
  6.                     var me = this,  
  7.                         args = arguments;  
  8.                     fcn.target = me;  
  9.                     fcn.method = method;  
  10.                     return (fcn.apply(scope || me || window, args) !== false) ?  
  11.                             method.apply(me || window, args) :  
  12.                             null;  
  13.                 };  
  14.     },  
 

该方法实现了类似拦截器的功能,传递的参数fcn在原函数之前调用。如果fcn的返回值为false,则原函数不会被调用。即函数fcn拦截时,如果fcn返回false,将被拦截,true则执行。以下说明方法中的部分语句。

 

var method = this,因为是给Function.prototype扩展,因此其prototype上挂的所有的函数,函数内的this都是Function,即函数自身。看下面例子

Js代码   收藏代码
  1. Function.prototype.test = function(){  
  2.     alert(this);  
  3. };  
  4. function fn(){return 'test';}  
  5. fn.test();  

  结果输出

function fn() {

    return "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就是谁。如:

 

Js代码   收藏代码
  1. function oldFn(){  
  2.     alert('test');  
  3. }  
  4. function ret(){  
  5.     return false;  
  6. }  
  7. var newFn = oldFn.createInterceptor(ret);  
  8. newFn();  

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

 

Js代码   收藏代码
  1. function oldFn(){  
  2.     alert('test');  
  3. }  
  4. function ret(){  
  5.     return false;  
  6. }  
  7. var obj = {name:'jack'};  
  8. obj.method = oldFn.createInterceptor(ret);  
  9. obj.method();  

  (fcn.apply(scope || me || window, args) !== false),所传参数fcn被执行,执行上下文优先是scope,其次是me,最后是window。返回结果不等于false才执行method。method执行上下文先为me,me不存在则是window。

 

现把官方例子贴出来

Js代码   收藏代码
  1. var sayHi = function(name){  
  2.     alert('Hi, ' + name);  
  3. }  
  4.   
  5. sayHi('Fred'); // alerts "Hi, Fred"  
  6.   
  7. // create a new function that validates input without  
  8. // directly modifying the original function:  
  9. var sayHiToFriend = sayHi.createInterceptor(function(name){  
  10.     return name == 'Brian';  
  11. });  
  12.   
  13. sayHiToFriend('Fred');  // no alert  
  14. sayHiToFriend('Brian'); // alerts "Hi, Brian"  

 

该例子在createInterceptor中  fcn.apply(scope || me || window, args) 相当于直接执行

function(name){

    return name == 'Brian';

}

只是将函数绑定到另外一个对象上(scope || me || window)去运行

method 实际为sayHi

 

createCallback方法

 

Js代码   收藏代码
  1. //创建一个回调函数,该回调传递参数的形式为:arguments[0],...  
  2.     createCallback : function(/*args...*/){  
  3.         // make args available, in function below  
  4.         var args = arguments,  
  5.             method = this;  
  6.         return function() {  
  7.             return method.apply(window, args);  
  8.         };  
  9.     },  
 

这个方法非常有用,实现简单。返回一个新函数,新函数内执行method,会把外面的参数给传进来。
初学者经常 纠结于给事件handler传参数  。createCallback 解决了给DOM事件handler(监听器)传参问题。
createCallback 不仅用在DOM事件handler上你完全可以自定义事件,设计一套属于自己的 观察者模式  API。即每个类有自己的事件,如 LTMaps  ,除了拥有属性,方法还有许多事件,如移动地图(move),缩放地图(zoom)。Ext的众多UI组件也都是这种模式,Ext.Panel 具有afterlayout,close等事件。

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

 

 

createDelegate 方法

 

Js代码   收藏代码
  1. //创建一个委派对象(就是回调),该对象的作用域指向obj。对于任何函数来说都是可以直接调用的。  
  2.     //obj : Object (可选的) 自定义的作用域对象。(optional) The object for which the scope is set   
  3.     //args : Array (可选的) 覆盖该次调用的参数列表。(默认为该函数的arguments)。(optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)   
  4.     //appendArgs : Boolean/Number(可选的) 如果该参数为true,将args加载到该函数的后面,如果该参数为数字类型,则args将插入到所指定的位置。  
  5.     //顺便说一下Array.prototype.slice(start,end)的用法,返回选定的所有元素的数组,start,end可选参数,默认为返回所有元素  
  6.     createDelegate : function(obj, args, appendArgs){  
  7.         var method = this;  
  8.         return function() {  
  9.             var callArgs = args || arguments;  
  10.             if (appendArgs === true){  
  11.                 callArgs = Array.prototype.slice.call(arguments, 0);  
  12.                 callArgs = callArgs.concat(args);  
  13.             }else if (Ext.isNumber(appendArgs)){  
  14.                 callArgs = Array.prototype.slice.call(arguments, 0); // copy arguments first  
  15.                 var applyArgs = [appendArgs, 0].concat(args); // create method call params  
  16.                 Array.prototype.splice.apply(callArgs, applyArgs); // splice them in  
  17.             }  
  18.             return method.apply(obj || window, callArgs);  
  19.         };  
  20.     },  

 

createDelegate 比 createCallback 更强大,除了能解决回调函数传参问题。还能控制:
1, 自定义参数是否覆盖默认参数(如 DOM事件对象  作为handler第一个参数)
2, 自定义参数的位置

内部实现:取自身(var method=this),返回一个新function,该function调用自身(method.apply),同时指定上下文(obj||window)及参数(callArgs)。就这么简单,细节之处在于对参数的控制。

1,只传obj和args时将覆盖回调函数默认参数(DOM事件对象)

Js代码   收藏代码
  1. <a href="#" id="aa">SINA</a>  
  2. <script type="text/javascript">  
  3.     var aa = document.getElementById('aa');  
  4.     function sayName(name){  
  5.         alert('hello, ' + name);  
  6.     }  
  7.     var sayName2 = sayName.createDelegate(aa,['jack']);  
  8.     aa.onclick = sayName2;  
  9. </script>  

 2,三个参数都传,appendArgs为true时,默认参数(DOM事件对象)位置不变(第一个),自定义参数args在最后

Js代码   收藏代码
  1. <a href="#" id="aa">SINA</a>  
  2. <script type="text/javascript">  
  3.     var aa = document.getElementById('aa');  
  4.     function sayName(){       
  5.         alert('实际参数长度:' + arguments.length);  
  6.         alert('hello, ' + arguments[0]);  
  7.         alert('hi, ' + arguments[1]);  
  8.     }  
  9.     var sayName2 = sayName.createDelegate(aa,['jack'],true);  
  10.     aa.onclick = sayName2;  
  11. </script>  

 3, 三个参数都传,appendArgs为数字时将指定自定义参数的位置

Js代码   收藏代码
  1. <a href="#" id="aa">SINA</a>  
  2. <script type="text/javascript">  
  3.     var aa = document.getElementById('aa');  
  4.     function sayName(name){       
  5.         alert('实际参数长度:' + arguments.length);  
  6.         alert('hello, ' + arguments[0]);  
  7.         alert('hi, '+ arguments[1]);  
  8.         alert('hi, '+ arguments[2]);  
  9.     }  
  10.     var sayName2 = sayName.createDelegate(aa,['jack','lily'],0);  
  11.     aa.onclick = sayName2;  
  12. </script>  

 

defer 方法

 

Js代码   收藏代码
  1. /** 
  2.      * 延迟调用该函数 
  3.      * @param {} millis 延迟时间,以毫秒为单位(如果是0则立即执行) 
  4.      * @param {} obj (可选的) fcn的作用域(默认指向原函数或window) 
  5.      * @param {} args (可选的) 覆盖原函数的参数列表(默认为该函数的arguments) 
  6.      * @param {} appendArgs (可选的)如果该参数为true,将args加载到该函数的后面,如果该参数为数字类型,则args将插入到所指定的位置 
  7.      * @return {Number} 
  8.      */  
  9.     defer : function(millis, obj, args, appendArgs){  
  10.         var fn = this.createDelegate(obj, args, appendArgs);  
  11.         if(millis > 0){  
  12.             return setTimeout(fn, millis);  
  13.         }  
  14.         fn();  
  15.         return 0;  
  16.     }  

你可能感兴趣的:(ExtJs源码分析与学习—ExtJs核心代码(三))