- 浏览: 319265 次
- 性别:
- 来自: 济南
文章分类
- 全部博客 (221)
- J2SE心得 (4)
- 经典帖子 (8)
- 亲身经历 (9)
- SSH框架 (12)
- 数据库 (10)
- java基础知识 (41)
- java解惑 (17)
- 软件测试 (0)
- JSP (6)
- JavaScript (8)
- jQuery学习 (12)
- 硬件知识 (1)
- 工具类 (14)
- 面试专题 (4)
- Struts2专题(学习) (14)
- Spring源码分析专题(学习) (15)
- JavaScript专题(学习) (8)
- ExtJs专题(学习) (6)
- Java Web快速入门——全十讲 (10)
- web前台 (1)
- J2ME手机方面 (1)
- 积累整理 (1)
- MyEclipse工具篇 (10)
- oracle (1)
- Android基础 (1)
最新评论
-
youjianbo_han_87:
上传成功后,无法跳转到success页面,会报2038和404 ...
Struts2使用FlashFileUpload.swf实现批量文件上传 -
showzh:
...
MyEclipse 怎么安装SVN插件 -
wpf523:
赞一个啊,楼主加油
一些比较复杂的运算符(二) -
独步天下:
request.getSession().getAttribute() 和request.getSession().setAttribute() -
HelloJava1234:
thank you
怎么改变MyEclipse默认的jsp打开方式
原生 Function 类:
参考手册并没有过多介绍 JS 内建的 Function 对象,只是介绍了如何用 new Function(name,arg…); 这样的方法来创建一个新的函数。
另外,通过其它资料我们还可以了解到,每个被定义的 function 都有 length 属性,它描述这个 function 定义时的实际参数个数。另一个属性就是原型: prototype ,当一个 function 被调用的时候, js 引擎负责创建 function 的 prototype 属性。
有可能内建的 Function 类本身没有什么其它实际可用的属性或方法;另一种可能是 js 不想暴露关于 Function 类的过多细节。因为如果这样做可能带来过度的复杂性。
Ext 对 Function 的扩展
Ext 为 Function 扩展了五个实例方法: createCallback() 、 createDelegate() 、 defer() 、 createSequence() 、 createInterceptor() 。
也就是说,在使用 Ext 框架时,对于每个自定义的函数,都可以直接调用这些方法。
下面来看源码(注释都已翻译成中文)。
- <SPAN style="FONT-SIZE: medium">/**
- * @ Function类
- *这些方法对于每个Function对象都有效(任何一个js函数)。
- */
- Ext.apply(Function.prototype, {
- /*该方法用来创建一个可以传递参数的回调函数。
- *该方法可以直接在任何一个function上调用。
- *例如:<code>myFunction.createCallback(arg1, arg2)</code>,这样就创建了一个绑定了
- *两个参数的方法。
- *如果回调函数需要特定的作用域,请用createDelegate()方法替代。
- *createCallback()方法返回的函数总是在window作用域(顶级作用域)中执行。
- *如果你想给一个回调方法传递参数,则需要使用该方法。如果不需要参数,你可以直
- *接简单地传递一个函数的引用给需要回调的地方就可以了(例如callback: myFn)。(译者*注:这句话的意思就是说,如果你不需要向回调函数传递参数,就没有必要使用*createCallback()这个方法,直接按照常规的方式写就可以了)。
- *然而,(译者注:按照常规的写法的话),如果你尝试向回调函数传递参数,(例如callback: *myFn(arg1, arg2))。那么函数在解析的时候就会被简单地执行。(译者注:而不是你期
- *望的在发生某件事情之后再来回调。)
- *createCallback()的示例用法如下:
- <pre><code>
- var sayHi = function(name){
- alert('Hi, ' + name);
- }
- // clicking the button alerts "Hi, Fred"
- new Ext.Button({
- text: 'Say Hi',
- renderTo: Ext.getBody(),
- handler: sayHi.createCallback('Fred')
- });
- </code></pre>
- *@返回值 {Function} 新的回调函数。
- */
- createCallback : function(/*args...*/){
- //使得传递进来的参数在下面的function中可用。(译者注:这里实际上是返回了//一个闭包函数,然后使用window来调用原来的函数,并把需要的参数传递进去。)
- var args = arguments;
- var method = this;
- return function() {
- return method.apply(window, args);
- };
- },
- /*创建一个代理(回调)函数,把作用域设置到参数obj上。
- *该函数可以直接再任何函数上调用。例如:<code>this.myFunction.createDelegate(this, *[arg1, arg2])</code>,这将创建一函数并自动把作用域设置到obj上,这样的话,新的*callback函数中的this属性指向obj对象。
- *用法示例:
- * <pre><code>
- var sayHi = function(name){
- //注意这里的this.text用法。这个函数期望在一个包含text属性的作用域中//执行。在这个例子中,这个’this’属性指向了下面传入createDelegate方法//的btn对象。
- alert('Hi, ' + name + '. You clicked the "' + this.text + '" button.');
- }
- var btn = new Ext.Button({
- text: 'Say Hi',
- renderTo: Ext.getBody()
- });
- //回调函数将在button实例的作用域中执行。
- //点击按钮,将弹出"Hi, Fred. You clicked the ‘Say Hi’ button."
- btn.on('click', sayHi.createDelegate(btn, ['Fred']));
- </code></pre>
- * @参数1 {Object} obj (可选) 需要设置的目标作用域对象。
- * @参数2 {Array} args (可选) 覆盖默认的调用参数。(默认为调用者传递进来的参数。)
- * @参数3 {Boolean/Number} appendArgs (可选) 如果为true,(第二个参数)args被
- *添加到调用参数中而不是覆盖。如果为数字,(第二个参数)args将被插入到指定的*位置。
- * @返回值 {Function} 新的函数
- */
- 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(typeof appendArgs == "number"){
- 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);
- };
- },
- /*在指定的毫秒数之后调用函数,同时可以指定特定的作用域。
- *用法示例:
- * <pre><code>
- var sayHi = function(name){
- alert('Hi, ' + name);
- }
- // 立即执行:
- sayHi('Fred');
- //2秒后执行:
- sayHi.defer(2000, this, ['Fred']);
- //有时候这种语法在推迟执行一个匿名的函数的时候非常有用:
- (function(){
- alert('Anonymous');
- }).defer(100);
- </code></pre>
- * @参数1 {Number} millis 设置调用setTimeout的毫秒数(如果为0函数立即被调用)。
- * @参数2 {Object} obj (可选) 需要设置的特定作用域
- * @参数2 {Array} args (可选) 覆盖默认的调用参数。(默认为调用者传递进来的参数。)
- * @参数3 {Boolean/Number} appendArgs (可选) 如果为true,(第二个参数)args被
- * 添加到调用参数中而不是覆盖。如果为数字,(第二个参数)args将被插入到指定的* 位置。
- * @返回值 {Number} 定时器id,可以用来清除定时器。
- */
- defer : function(millis, obj, args, appendArgs){
- var fn = this.createDelegate(obj, args, appendArgs);
- if(millis){
- return setTimeout(fn, millis);
- }
- fn();
- return 0;
- },
- /*使用原始的函数和传递进来的函数来创建一个组合的函数调用顺序(译者注:这是一*种类似管道式的调用效果,使用第一个函数的参数来调用第二个函数)。
- *最终执行的函数返回原始函数的结果。
- *使用原始函数的参数来调用传递进来的函数。
- *示例用法:
- * <pre><code>
- var sayHi = function(name){
- alert('Hi, ' + name);
- }
- sayHi('Fred'); //弹出 "Hi, Fred"
- var sayGoodbye = sayHi.createSequence(function(name){
- alert('Bye, ' + name);
- });
- sayGoodbye('Fred'); //两个alert都会弹出
- </code></pre>
- * @参数1 {Function} fcn 需要顺序执行的函数
- *@参数2 {Object} scope (optional) 传递进来函数的作用域 (默认作用域为原始函数的*作用域或window)
- * @返回值 {Function} 新的函数
- */
- createSequence : function(fcn, scope){
- if(typeof fcn != "function"){
- return this;
- }
- var method = this;
- return function() {
- var retval = method.apply(this || window, arguments);
- fcn.apply(scope || this || window, arguments);
- return retval;
- };
- },
- /*创建一个拦截函数。传入的函数在原始的函数之前执行。如果传入的函数返回false,*就不执行原始的函数。最终函数返回原始函数的执行结果。传递进来的函数使用原始*函数的参数来调用。
- *用法示例:
- * <pre><code>
- var sayHi = function(name){
- alert('Hi, ' + name);
- }
- sayHi('Fred'); // 弹出 "Hi, Fred"
- //创建一个新的函数来校验输入,而不直接去修改原始函数。
- var sayHiToFriend = sayHi.createInterceptor(function(name){
- return name == 'Brian';
- });
- sayHiToFriend('Fred'); //没有弹出
- sayHiToFriend('Brian'); // 弹出"Hi, Brian"
- </code></pre>
- * @参数1 {Function} fcn 需要在原始函数调用之前被调用的函数
- *@参数2 {Object} scope (可选) 拦截器的作用域(默认为原始函数的作用域或者window)
- * @返回值 {Function} 新的函数
- */
- createInterceptor : function(fcn, scope){
- if(typeof fcn != "function"){
- return this;
- }
- var method = this;
- return function() {
- fcn.target = this;
- fcn.method = method;
- if(fcn.apply(scope || this || window, arguments) === false){
- return;
- }
- return method.apply(this || window, arguments);
- };
- }
- });
- </SPAN>
/**
* @ Function类
*这些方法对于每个Function对象都有效(任何一个js函数)。
*/
Ext.apply(Function.prototype, {
/*该方法用来创建一个可以传递参数的回调函数。
*该方法可以直接在任何一个function上调用。
*例如:<code>myFunction.createCallback(arg1, arg2)</code>,这样就创建了一个绑定了
*两个参数的方法。
*如果回调函数需要特定的作用域,请用createDelegate()方法替代。
*createCallback()方法返回的函数总是在window作用域(顶级作用域)中执行。
*如果你想给一个回调方法传递参数,则需要使用该方法。如果不需要参数,你可以直
*接简单地传递一个函数的引用给需要回调的地方就可以了(例如callback: myFn)。(译者*注:这句话的意思就是说,如果你不需要向回调函数传递参数,就没有必要使用*createCallback()这个方法,直接按照常规的方式写就可以了)。
*然而,(译者注:按照常规的写法的话),如果你尝试向回调函数传递参数,(例如callback: *myFn(arg1, arg2))。那么函数在解析的时候就会被简单地执行。(译者注:而不是你期
*望的在发生某件事情之后再来回调。)
*createCallback()的示例用法如下:
<pre><code>
var sayHi = function(name){
alert('Hi, ' + name);
}
// clicking the button alerts "Hi, Fred"
new Ext.Button({
text: 'Say Hi',
renderTo: Ext.getBody(),
handler: sayHi.createCallback('Fred')
});
</code></pre>
*@返回值 {Function} 新的回调函数。
*/
createCallback : function(/*args...*/){
//使得传递进来的参数在下面的function中可用。(译者注:这里实际上是返回了//一个闭包函数,然后使用window来调用原来的函数,并把需要的参数传递进去。)
var args = arguments;
var method = this;
return function() {
return method.apply(window, args);
};
},
/*创建一个代理(回调)函数,把作用域设置到参数obj上。
*该函数可以直接再任何函数上调用。例如:<code>this.myFunction.createDelegate(this, *[arg1, arg2])</code>,这将创建一函数并自动把作用域设置到obj上,这样的话,新的*callback函数中的this属性指向obj对象。
*用法示例:
* <pre><code>
var sayHi = function(name){
//注意这里的this.text用法。这个函数期望在一个包含text属性的作用域中//执行。在这个例子中,这个’this’属性指向了下面传入createDelegate方法//的btn对象。
alert('Hi, ' + name + '. You clicked the "' + this.text + '" button.');
}
var btn = new Ext.Button({
text: 'Say Hi',
renderTo: Ext.getBody()
});
//回调函数将在button实例的作用域中执行。
//点击按钮,将弹出"Hi, Fred. You clicked the ‘Say Hi’ button."
btn.on('click', sayHi.createDelegate(btn, ['Fred']));
</code></pre>
* @参数1 {Object} obj (可选) 需要设置的目标作用域对象。
* @参数2 {Array} args (可选) 覆盖默认的调用参数。(默认为调用者传递进来的参数。)
* @参数3 {Boolean/Number} appendArgs (可选) 如果为true,(第二个参数)args被
*添加到调用参数中而不是覆盖。如果为数字,(第二个参数)args将被插入到指定的*位置。
* @返回值 {Function} 新的函数
*/
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(typeof appendArgs == "number"){
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);
};
},
/*在指定的毫秒数之后调用函数,同时可以指定特定的作用域。
*用法示例:
* <pre><code>
var sayHi = function(name){
alert('Hi, ' + name);
}
// 立即执行:
sayHi('Fred');
//2秒后执行:
sayHi.defer(2000, this, ['Fred']);
//有时候这种语法在推迟执行一个匿名的函数的时候非常有用:
(function(){
alert('Anonymous');
}).defer(100);
</code></pre>
* @参数1 {Number} millis 设置调用setTimeout的毫秒数(如果为0函数立即被调用)。
* @参数2 {Object} obj (可选) 需要设置的特定作用域
* @参数2 {Array} args (可选) 覆盖默认的调用参数。(默认为调用者传递进来的参数。)
* @参数3 {Boolean/Number} appendArgs (可选) 如果为true,(第二个参数)args被
* 添加到调用参数中而不是覆盖。如果为数字,(第二个参数)args将被插入到指定的* 位置。
* @返回值 {Number} 定时器id,可以用来清除定时器。
*/
defer : function(millis, obj, args, appendArgs){
var fn = this.createDelegate(obj, args, appendArgs);
if(millis){
return setTimeout(fn, millis);
}
fn();
return 0;
},
/*使用原始的函数和传递进来的函数来创建一个组合的函数调用顺序(译者注:这是一*种类似管道式的调用效果,使用第一个函数的参数来调用第二个函数)。
*最终执行的函数返回原始函数的结果。
*使用原始函数的参数来调用传递进来的函数。
*示例用法:
* <pre><code>
var sayHi = function(name){
alert('Hi, ' + name);
}
sayHi('Fred'); //弹出 "Hi, Fred"
var sayGoodbye = sayHi.createSequence(function(name){
alert('Bye, ' + name);
});
sayGoodbye('Fred'); //两个alert都会弹出
</code></pre>
* @参数1 {Function} fcn 需要顺序执行的函数
*@参数2 {Object} scope (optional) 传递进来函数的作用域 (默认作用域为原始函数的*作用域或window)
* @返回值 {Function} 新的函数
*/
createSequence : function(fcn, scope){
if(typeof fcn != "function"){
return this;
}
var method = this;
return function() {
var retval = method.apply(this || window, arguments);
fcn.apply(scope || this || window, arguments);
return retval;
};
},
/*创建一个拦截函数。传入的函数在原始的函数之前执行。如果传入的函数返回false,*就不执行原始的函数。最终函数返回原始函数的执行结果。传递进来的函数使用原始*函数的参数来调用。
*用法示例:
* <pre><code>
var sayHi = function(name){
alert('Hi, ' + name);
}
sayHi('Fred'); // 弹出 "Hi, Fred"
//创建一个新的函数来校验输入,而不直接去修改原始函数。
var sayHiToFriend = sayHi.createInterceptor(function(name){
return name == 'Brian';
});
sayHiToFriend('Fred'); //没有弹出
sayHiToFriend('Brian'); // 弹出"Hi, Brian"
</code></pre>
* @参数1 {Function} fcn 需要在原始函数调用之前被调用的函数
*@参数2 {Object} scope (可选) 拦截器的作用域(默认为原始函数的作用域或者window)
* @返回值 {Function} 新的函数
*/
createInterceptor : function(fcn, scope){
if(typeof fcn != "function"){
return this;
}
var method = this;
return function() {
fcn.target = this;
fcn.method = method;
if(fcn.apply(scope || this || window, arguments) === false){
return;
}
return method.apply(this || window, arguments);
};
}
});
总结 :
从以上的源码分析可以看出,对原生 Function 类的扩展全部使用了闭包。里面模拟了高级语言里面才有的代理、拦截器 。知道 Java 里面 Spring 的人对这里的代理模式 应该不陌生,知道 Struts2 的人应该很熟悉拦截器 的概念,后面还有模板 (XTemplate) ,相信 C++ 的 fans 读到的时候肯定会很兴奋。一点小小的感慨:对于编程,编程的思想和算法 是可以超越语言、甚至超越所谓的架构而存在的。如果我们能够把这些模式、这些思想烂熟于胸,使用起来收放自如,又何必去在乎何种语言,何必去争论所谓的 C/S 还是 B/S ?
我相信,通过仔细阅读 Ext 的源代码,必定能对那些耳熟能详的所谓模式和思想有更进一层的体会。
Ext 对原生对象的扩展到这里结束。
(今天早上找了一个 Easy CHM ,想把翻译的这些东西压缩成帮助文档,结果搞出来样子非常丑,希望哪位善于制作 CHM 的高手能给我一点帮助,能达到以下这种效果就成了,Ext提供的HTML式的效果就是这样的。这个图片是网上流传比较多的一份 Ext2.0 的 CHM 文档,没有翻译,好多东西还有错误在里面,后期有时间我想来尝试一遍阅读 2.2 的源码一边翻译这份 API 。练练 E 文,也算帮助一下他人 ^_^ )。
如你觉得自己 E 文还行,愿意提供帮助,可加 qun : 88403922 参与
发表评论
-
《仔仔细细分析Ext》 脚本,你的效率到底损失在哪里?:Ext对Array对象的扩展
2009-12-01 12:57 812导言 差不多所有的 js 库都会对原生的 ... -
《仔仔细细分析Ext》 Ext对Number类的扩展
2009-12-01 12:56 798原生 Number 类: 包含五个静态属性和六个实例方法, ... -
《仔仔细细分析Ext》 Ext对String类的扩展
2009-12-01 12:54 931原生 String 类: 一个 leng ... -
《仔仔细细分析Ext》 Ext的事件机制源码详解:Ext.onReady()方法的原理是什么?
2009-12-01 12:53 1750导言 Ext 封装了自己的事件机制,除了支持 ... -
《仔仔细细分析Ext》 第一章 必须理解Ext.extend函数
2009-12-01 12:51 761显然了,从函数名就可 ...
相关推荐
7. **主题定制**:EXTJS 4.2.0可能扩展了主题支持,让开发者能够更轻松地创建自定义皮肤,满足特定品牌和设计需求。 8. **调试与测试工具**:为了帮助开发者更好地调试和测试EXTJS应用,4.2.0版本可能增强了开发...
2. 扩展访问控制列表(Extended ACL):编号为100-199,对源地址、目的地址、源端口、目的端口和协议进行判断,通常放在离源端较近的接口上。 扩展ACL的特点: * 可以对源地址和目的地址进行判断 * 可以对源端口和...
这个故事讲述了民间打拐勇士仔仔的事迹,他是一个退伍的武警战士,致力于打击人口贩卖,尤其是儿童拐卖。仔仔通过网络监控,识别出人贩子的暗语,并与他们周旋,协助警方解救被拐儿童。 1. **网络监控与反拐策略**...
【仔仔学数学源码 C#4】是一个专门为幼儿园及小学生设计的数学运算软件,旨在帮助孩子们学习和掌握万位数以内的基本算术运算。这个项目采用C#编程语言的第四版本(C#4)编写,展示了如何利用C#的强大功能来创建教育...
2. **结构分析**:分析项目的目录结构和文件组织,了解模块划分和职责分配,这对理解整个系统架构至关重要。 3. **数据库交互**:查看与数据库相关的代码,了解数据的存储和查询方式,可能涉及SQL语句、ORM框架(如...
5. **兼容性与移植性**:GBA图书仔2 0.9版需要确保生成的电子书能在各种GBA硬件上正常运行,这涉及对不同GBA模拟器和真实硬件的兼容性测试。 6. **性能优化**:为了在低性能的GBA设备上流畅运行,软件需要进行性能...
这三个主要成分都是通过线性回归分析进一步研究的,结果表明城市用地的扩展与城市人口和GDP的增长之间存在高度正相关的关系,而进一步的偏相关分析发现,GDP增长是解释城市用地扩展的更重要因素。这意味着经济增长在...
这里有两份灵格斯词典,它们可以扩展jieba的基础词库,提高对年报中非标准词汇或行业特有词汇的识别率,确保分析的全面性。 会计科目词典包含了会计领域中常见的科目名称,如“应收账款”、“固定资产”等。在分析...
3. **文件系统**:选择合适的文件系统对嵌入式设备至关重要,例如JFFS2、YAFFS或ext4,这些文件系统有不同的优点和适用场景。 4. **实时性增强**:对于需要实时响应的嵌入式应用,可以通过RT-PREEMPT补丁或采用实时...
这些库提供了对EF的扩展,使得我们能够批量插入数据,显著提高性能。 1. **安装扩展库**: 要使用BulkInsert,首先需要通过NuGet包管理器安装对应的扩展库,例如`EntityFramework.BulkInsert`。在Visual Studio中...
宝仔视觉空间宝仔视觉空间宝仔视觉空间宝仔视觉空间
《农林牧渔类畜牧业行业长白猪领域分析报告》是一份深度研究畜牧业中长白猪养殖业的专业报告,旨在全面解析该领域的现状、发展趋势以及关键数据。报告内容包括但不限于行业概览、市场分析、生产情况、经济效益以及...
包括各个文本的关键词输出,可以控制关键词输出个数,也可以对关键词加入黑名单和白名单。 关于TextClassify文本分类系统的改进: 改进jieba中文分词词典 改进黑名单:增加停用词 改进白名单:增加专业词 在Text...
在死仔截图中,`Bitmap`类用于创建一个与屏幕分辨率相同的图像,然后将屏幕内容复制到这个位图对象中。 5. **Rectangle结构**:`Rectangle`结构用于定义一个矩形区域,它是截图的关键部分。在选择截图区域时,需要...
ANSYS作为一款强大的多物理场仿真软件,提供了丰富的功能来模拟地震对结构的影响,帮助工程师进行地震分析。本文将围绕“ANSYS地震分析.rar”这一综合学习科研包,探讨其包含的反应谱分析、时程分析、人工波生成以及...
Email tracker 扩展包
烯丙孕素对断奶母猪发情调控及产仔性能的影响_赵思友.caj
通过对这些命令流的学习,工程师可以掌握如何在ANSYS环境中对各种建筑结构进行精确、高效的分析,从而在设计阶段就能预见并解决潜在的结构问题,确保建筑物的安全性和耐久性。无论是初学者还是经验丰富的专业人士,...