ExtJs源码分析与学习—ExtJs核心代码(三)
2011-07-27 23:41
633 查看
Ext为javascript的一些对象进行了扩展,主要有String、Array和Function,以下只介绍Ext.js中提到的方法,其他的后续再介绍
Ext为String扩展了方法 format,该方法为String的静态方法(类方法),可以把字符串中特殊写法({0},{1})用指定的变量替换
Js代码
![](http://linder0209.iteye.com/images/icon_star.png)
//定义带标记的字符串,并用传入的字符替换标记。每个标记必须是唯一的,而且必须要像{0},{1}...{n}
//这样地自增长。
//var cls = 'my-class', text = 'Some text';
//var s = String.format('{0} ' '{1}', cls, text);
//s现在是字符串:s now contains the string: 'my-class' 'Some text'
format : function(format){
var args = Ext.toArray(arguments, 1);
return format.replace(/\{(\d+)\}/g, function(m, i){
return args[i];
});
}
Ext为Array扩展了方法 indexOf 和remove,这两个方法分别实现了索引和根据子元素删除对应的该元素
Js代码
![](http://linder0209.iteye.com/images/icon_star.png)
Ext.applyIf(Array.prototype, {
/**
* Checks whether or not the specified object exists in the array.
* @param {Object} o The object to check for
* @param {Number} from (Optional) The index at which to begin the search
* @return {Number} The index of o in the array (or -1 if it is not found)
*/
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;
},
/**
* Removes the specified object from the array. If the object is not found nothing happens.
* @param {Object} o The object to remove
* @return {Array} this array
*/
remove : function(o){
var index = this.indexOf(o);
if(index != -1){
this.splice(index, 1);
}
return this;
}
});
编者在实际开发中经常会用到以下两个方法,也很实用
Js代码
![](http://linder0209.iteye.com/images/icon_star.png)
/**
* 数组插入元素
* @param {} index 插入位置
* @param {} o 插入元素
* @return {}
*/
insert : function (index,o){
if(index <= 0){
return this.unshift(o);//插入到首元素
}
if(index >= this.length){
return this.push(o);//插入到末元素
}
var sub = this.slice(index, this.length);
this.length = index;
this.push(o);
for(var i = 0; i < sub.length; i++){
this.push(sub[i]);
}
return this;
},
/**
* 删除数组中指定的元素
* @param {} index
* @return {}
*/
removeAt : function(index){
if(index != -1){
this.splice(index, 1);
}
return this;
}
以下扩展String方法也很有用
Js代码
![](http://linder0209.iteye.com/images/icon_star.png)
Ext.applyIf(String,{
/**
* 把驼峰格式的字符串转换为-格式
* 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
* @param {} str
* @param {} conj
* @return {}
*/
humpToConnector : function(str, conj){
//str = !str ? str : String(str);
var index = str.search(/[A-Z]/);
if (index >= 0) {
var c = str.charAt(index);
return String.humpToConnector(str.substring(0, index) + conj
+ c.toLowerCase() + str.substring(index + 1), conj);
} else {
return str;
}
}
});
Ext对Function的扩展
createInterceptor方法
Js代码
![](http://linder0209.iteye.com/images/icon_star.png)
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;
};
},
该方法实现了类似拦截器的功能,传递的参数fcn在原函数之前调用。如果fcn的返回值为false,则原函数不会被调用。即函数fcn拦截时,如果fcn返回false,将被拦截,true则执行。以下说明方法中的部分语句。
var method = this,因为是给Function.prototype扩展,因此其prototype上挂的所有的函数,函数内的this都是Function,即函数自身。看下面例子
Js代码
![](http://linder0209.iteye.com/images/icon_star.png)
Function.prototype.test = function(){
alert(this);
};
function fn(){return 'test';}
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代码
![](http://linder0209.iteye.com/images/icon_star.png)
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了
Js代码
![](http://linder0209.iteye.com/images/icon_star.png)
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。
现把官方例子贴出来
Js代码
![](http://linder0209.iteye.com/images/icon_star.png)
var sayHi = function(name){
alert('Hi, ' + name);
}
sayHi('Fred'); // alerts "Hi, Fred"
// create a new function that validates input without
// directly modifying the original function:
var sayHiToFriend = sayHi.createInterceptor(function(name){
return name == 'Brian';
});
sayHiToFriend('Fred'); // no alert
sayHiToFriend('Brian'); // alerts "Hi, Brian"
该例子在createInterceptor中 fcn.apply(scope || me || window, args) 相当于直接执行
function(name){
return name == 'Brian';
}
只是将函数绑定到另外一个对象上(scope || me || window)去运行
method 实际为sayHi
createCallback方法
Js代码
![](http://linder0209.iteye.com/images/icon_star.png)
//创建一个回调函数,该回调传递参数的形式为:arguments[0],...
createCallback : function(/*args...*/){
// make args available, in function below
var args = arguments,
method = this;
return function() {
return method.apply(window, args);
};
},
这个方法非常有用,实现简单。返回一个新函数,新函数内执行method,会把外面的参数给传进来。
初学者经常 纠结于给事件handler传参数 。createCallback 解决了给DOM事件handler(监听器)传参问题。
createCallback 不仅用在DOM事件handler上你完全可以自定义事件,设计一套属于自己的 观察者模式 API。即每个类有自己的事件,如 LTMaps ,除了拥有属性,方法还有许多事件,如移动地图(move),缩放地图(zoom)。Ext的众多UI组件也都是这种模式,Ext.Panel 具有afterlayout,close等事件。
在给这些事件添加hanlder,又想传参或许也会用到 createCallback。
createDelegate 方法
Js代码
![](http://linder0209.iteye.com/images/icon_star.png)
//创建一个委派对象(就是回调),该对象的作用域指向obj。对于任何函数来说都是可以直接调用的。
//obj : Object (可选的) 自定义的作用域对象。(optional) The object for which the scope is set
//args : Array (可选的) 覆盖该次调用的参数列表。(默认为该函数的arguments)。(optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
//appendArgs : Boolean/Number(可选的) 如果该参数为true,将args加载到该函数的后面,如果该参数为数字类型,则args将插入到所指定的位置。
//顺便说一下Array.prototype.slice(start,end)的用法,返回选定的所有元素的数组,start,end可选参数,默认为返回所有元素
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事件对象)
Js代码
![](http://linder0209.iteye.com/images/icon_star.png)
<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在最后
Js代码
![](http://linder0209.iteye.com/images/icon_star.png)
<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为数字时将指定自定义参数的位置
Js代码
![](http://linder0209.iteye.com/images/icon_star.png)
<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>
defer 方法
Js代码
![](http://linder0209.iteye.com/images/icon_star.png)
/**
* 延迟调用该函数
* @param {} millis 延迟时间,以毫秒为单位(如果是0则立即执行)
* @param {} obj (可选的) fcn的作用域(默认指向原函数或window)
* @param {} args (可选的) 覆盖原函数的参数列表(默认为该函数的arguments)
* @param {} appendArgs (可选的)如果该参数为true,将args加载到该函数的后面,如果该参数为数字类型,则args将插入到所指定的位置
* @return {Number}
*/
defer : function(millis, obj, args, appendArgs){
var fn = this.createDelegate(obj, args, appendArgs);
if(millis > 0){
return setTimeout(fn, millis);
}
fn();
return 0;
}
Ext为String扩展了方法 format,该方法为String的静态方法(类方法),可以把字符串中特殊写法({0},{1})用指定的变量替换
Js代码
![](http://linder0209.iteye.com/images/icon_star.png)
//定义带标记的字符串,并用传入的字符替换标记。每个标记必须是唯一的,而且必须要像{0},{1}...{n}
//这样地自增长。
//var cls = 'my-class', text = 'Some text';
//var s = String.format('{0} ' '{1}', cls, text);
//s现在是字符串:s now contains the string: 'my-class' 'Some text'
format : function(format){
var args = Ext.toArray(arguments, 1);
return format.replace(/\{(\d+)\}/g, function(m, i){
return args[i];
});
}
Ext为Array扩展了方法 indexOf 和remove,这两个方法分别实现了索引和根据子元素删除对应的该元素
Js代码
![](http://linder0209.iteye.com/images/icon_star.png)
Ext.applyIf(Array.prototype, {
/**
* Checks whether or not the specified object exists in the array.
* @param {Object} o The object to check for
* @param {Number} from (Optional) The index at which to begin the search
* @return {Number} The index of o in the array (or -1 if it is not found)
*/
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;
},
/**
* Removes the specified object from the array. If the object is not found nothing happens.
* @param {Object} o The object to remove
* @return {Array} this array
*/
remove : function(o){
var index = this.indexOf(o);
if(index != -1){
this.splice(index, 1);
}
return this;
}
});
编者在实际开发中经常会用到以下两个方法,也很实用
Js代码
![](http://linder0209.iteye.com/images/icon_star.png)
/**
* 数组插入元素
* @param {} index 插入位置
* @param {} o 插入元素
* @return {}
*/
insert : function (index,o){
if(index <= 0){
return this.unshift(o);//插入到首元素
}
if(index >= this.length){
return this.push(o);//插入到末元素
}
var sub = this.slice(index, this.length);
this.length = index;
this.push(o);
for(var i = 0; i < sub.length; i++){
this.push(sub[i]);
}
return this;
},
/**
* 删除数组中指定的元素
* @param {} index
* @return {}
*/
removeAt : function(index){
if(index != -1){
this.splice(index, 1);
}
return this;
}
以下扩展String方法也很有用
Js代码
![](http://linder0209.iteye.com/images/icon_star.png)
Ext.applyIf(String,{
/**
* 把驼峰格式的字符串转换为-格式
* 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
* @param {} str
* @param {} conj
* @return {}
*/
humpToConnector : function(str, conj){
//str = !str ? str : String(str);
var index = str.search(/[A-Z]/);
if (index >= 0) {
var c = str.charAt(index);
return String.humpToConnector(str.substring(0, index) + conj
+ c.toLowerCase() + str.substring(index + 1), conj);
} else {
return str;
}
}
});
Ext对Function的扩展
createInterceptor方法
Js代码
![](http://linder0209.iteye.com/images/icon_star.png)
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;
};
},
该方法实现了类似拦截器的功能,传递的参数fcn在原函数之前调用。如果fcn的返回值为false,则原函数不会被调用。即函数fcn拦截时,如果fcn返回false,将被拦截,true则执行。以下说明方法中的部分语句。
var method = this,因为是给Function.prototype扩展,因此其prototype上挂的所有的函数,函数内的this都是Function,即函数自身。看下面例子
Js代码
![](http://linder0209.iteye.com/images/icon_star.png)
Function.prototype.test = function(){
alert(this);
};
function fn(){return 'test';}
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代码
![](http://linder0209.iteye.com/images/icon_star.png)
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了
Js代码
![](http://linder0209.iteye.com/images/icon_star.png)
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。
现把官方例子贴出来
Js代码
![](http://linder0209.iteye.com/images/icon_star.png)
var sayHi = function(name){
alert('Hi, ' + name);
}
sayHi('Fred'); // alerts "Hi, Fred"
// create a new function that validates input without
// directly modifying the original function:
var sayHiToFriend = sayHi.createInterceptor(function(name){
return name == 'Brian';
});
sayHiToFriend('Fred'); // no alert
sayHiToFriend('Brian'); // alerts "Hi, Brian"
该例子在createInterceptor中 fcn.apply(scope || me || window, args) 相当于直接执行
function(name){
return name == 'Brian';
}
只是将函数绑定到另外一个对象上(scope || me || window)去运行
method 实际为sayHi
createCallback方法
Js代码
![](http://linder0209.iteye.com/images/icon_star.png)
//创建一个回调函数,该回调传递参数的形式为:arguments[0],...
createCallback : function(/*args...*/){
// make args available, in function below
var args = arguments,
method = this;
return function() {
return method.apply(window, args);
};
},
这个方法非常有用,实现简单。返回一个新函数,新函数内执行method,会把外面的参数给传进来。
初学者经常 纠结于给事件handler传参数 。createCallback 解决了给DOM事件handler(监听器)传参问题。
createCallback 不仅用在DOM事件handler上你完全可以自定义事件,设计一套属于自己的 观察者模式 API。即每个类有自己的事件,如 LTMaps ,除了拥有属性,方法还有许多事件,如移动地图(move),缩放地图(zoom)。Ext的众多UI组件也都是这种模式,Ext.Panel 具有afterlayout,close等事件。
在给这些事件添加hanlder,又想传参或许也会用到 createCallback。
createDelegate 方法
Js代码
![](http://linder0209.iteye.com/images/icon_star.png)
//创建一个委派对象(就是回调),该对象的作用域指向obj。对于任何函数来说都是可以直接调用的。
//obj : Object (可选的) 自定义的作用域对象。(optional) The object for which the scope is set
//args : Array (可选的) 覆盖该次调用的参数列表。(默认为该函数的arguments)。(optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
//appendArgs : Boolean/Number(可选的) 如果该参数为true,将args加载到该函数的后面,如果该参数为数字类型,则args将插入到所指定的位置。
//顺便说一下Array.prototype.slice(start,end)的用法,返回选定的所有元素的数组,start,end可选参数,默认为返回所有元素
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事件对象)
Js代码
![](http://linder0209.iteye.com/images/icon_star.png)
<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在最后
Js代码
![](http://linder0209.iteye.com/images/icon_star.png)
<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为数字时将指定自定义参数的位置
Js代码
![](http://linder0209.iteye.com/images/icon_star.png)
<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>
defer 方法
Js代码
![](http://linder0209.iteye.com/images/icon_star.png)
/**
* 延迟调用该函数
* @param {} millis 延迟时间,以毫秒为单位(如果是0则立即执行)
* @param {} obj (可选的) fcn的作用域(默认指向原函数或window)
* @param {} args (可选的) 覆盖原函数的参数列表(默认为该函数的arguments)
* @param {} appendArgs (可选的)如果该参数为true,将args加载到该函数的后面,如果该参数为数字类型,则args将插入到所指定的位置
* @return {Number}
*/
defer : function(millis, obj, args, appendArgs){
var fn = this.createDelegate(obj, args, appendArgs);
if(millis > 0){
return setTimeout(fn, millis);
}
fn();
return 0;
}
相关文章推荐
- ExtJs源码分析与学习—ExtJs核心代码(一)
- ExtJs源码分析与学习—ExtJs核心代码扩展
- ExtJs源码分析与学习—ExtJs核心代码(二)
- 学习Spark的入门教程——《Spark核心源码分析与开发实战》
- java核心基础--jdk源码分析学习--Hashtable
- 【NopCommerce源码架构学习-二】单例模式实现代码分析
- Spring AOP源码学习 最核心代码
- Android 之 三级缓存(内存!!!、本地、网络)及内存LruCache扩展 及源码分析--- 学习和代码讲解
- ExtJs源码分析与学习—ExtJs元素Element(二)
- ExtJs源码分析与学习—ExtJs事件机制(五)
- 学习Redux之分析Redux核心代码分析
- java8学习之Collector源码分析与收集器核心
- java核心基础--jdk源码分析学习--LinkedList
- ExtJs源码分析与学习—ExtJs元素Element(三)
- java核心基础--jdk源码分析学习--TreeMap
- 【原创】动态图像监测开源代码 motion 学习 ----- Motion源码分析(1)
- ExtJs源码分析与学习—ExtJs元素Element(四)
- ExtJs源码分析与学习—ExtJs元素Element(一)
- java核心基础--jdk源码分析学习--基本数据类型
- 【原创】动态图像监测开源代码 motion 学习 ----- Motion源码分析(1)