?ExtJs对JavaScript的内建对象进行了扩展,对什么Object、Date、Array、Function、String的扩展,扩展方法想必诸位都烂熟于心了:用prototype的办法。这一篇讲一讲Function扩展的精妙之处,之所以突然研究这个问题,是因为我在研究 Ext.data.Store的源代码时,看到一行代码:
this.reader.onMetaChange = this.onMetaChange.createDelegate(this);
当初,我在研究Ext.js中的代码时,对于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);
??????? };
??? },
createDelegate函数的作用是,为指定函数创建一个回调函数,注意是创建一个新的函数返回,它返回的是一个新函数。我以前一直不明白,为什么要这么做,就像上面红色的那行代码,相信大伙与我一样,都在想,为什么不是写成这样:
this.reader.onMetaChange=this.onMetaChange;
不是应当这样写的吗?如果用过dotnet,那么委托一定是晓得了,javascript中的函数跟c#的委托一样,有很相近的意义,为什么c#中能这样写,JavaScript中不能这样写呢?
一切都因为this,this这个东西见风使舵,像上面onMetaChange这函数,实际调用时是在reader中,那么如果 onMetaChange中使用了this关键字,那么,this是指向reader的,而不是指向onMetaChange的定义环境所对应的 this。而事实上,我们往往想把这个this指向函数的定义环境,这也正是回调的最招人喜欢的地方,然而,因为this的问题,回调就不能像上面那样直接赋值。还得做些手脚,得让函数调用时scope为当前定义环境。
改变一个函数执行的scope,熟翻JavaScript的兄弟一定晓得要用:call、apply。至此,createDelegate的产生背景、作用都作了个交代。
createDelegate(this),调用时,一般直接传个this就行了,当真是妙啊。事实上,我上面讲的一通道理清楚了,这个函数的代码就没有秘密可言了。关键就是一个this。我现在感叹,你对JavaScript的造诣与你对this的领悟层次成正比。
既然讲了createDelegate,其他几个扩展函数一并讲了。
??? createCallback : function(/*args...*/){
??????? // make args available, in function below
??????? var args = arguments;
??????? var method = this;
??????? return function() {
??????????? return method.apply(window, args);
??????? };
??? }
也是创建调用者的回调,不过,回调函数的scope为window。相当于createDelegate(window)。没什么讲的。
??? defer : function(millis, obj, args, appendArgs){
??????? var fn = this.createDelegate(obj, args, appendArgs);
??????? if(millis){
??????????? return setTimeout(fn, millis);
??????? }
??????? fn();
??????? return 0;
??? },
此函数调用一次就让函数延迟调用一次。对setTimeout的封装罢了。如果没有定义延时参数,那么就马上执行。这个函数也没有技术性可言。
??? 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;
??????? };
??? },
这个函数就有点意思了,刚开始研究ext.js的时候还没有看明白,它的作用是在返回一个函数,此函数先调用“调用函数”,后调用传递进来的函数。这句话可能还没说清,见示例如下:
function A(){alert("第一个执行!");return 1;}
function B(){alert("第二个执行!");return 2;}
function C(){alert("第三个执行!");return 3;}
var D=A.createSequence(B).createSequence(C);
var result=D();
上面代码产生的效果是:
第一弹出框显示:第一个执行!
第二弹出框显示:第二个执行!
第三弹出框显示:第三个执行!
result的值为:3。
这下子诸位都明白了吧。用过dotnet的知道,委托变量有这种类似的功能。就是累加执行的效果。
??? 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);
??????? };
??? }
这个函数也有点意思,有创意,它返回被调用函数的回调,这个回调是条件执行的,执行条件是createInterceptor传入的那个函数返回真。示例代码如下:
function A(){}
var B=A.createInterceptor(function(i){return i>0;});
B(1),则A被执行,如果调用B(-1),A则不被执行。B的作用就是如果传入的第一个参数的值大于0时A才被执行,否则不执行。
相当于原有函数的功能不变,只是加个执行条件。这个想法着实巧妙。这一招现在想来,也可以用到c#中
详细解决方案
extJs 2.1学习笔记(Function扩张篇)
热度:130 发布时间:2013-11-08 17:52:01.0
相关解决方案
- Extjs grid 失去选中行的列数据
- jquery中$(document).ready(function()是jquery开始要写的一句话,javaWeb项目中,这句话什么时候开始实施呢
- extjs 后台有数据,但是返回到页面为空,jsonStore加载错误,这是咋回事
- 求解$.post(url,{},function(){});回调函数中怎么使用判断语句
- S2SH、EXTJS、JSON调整后,EXTJS接收不到Struts2的Action传回的值,无语
- extjs 简单有关问题
- extjs+struts2解决办法
- (function(){//coding.})() 请教这是什么意思
- fatal error; call to a member function query() on a non-object异常求回答啊 php+sqlite
- ExtJs 处理 datetime 有关问题
- function 施行 *action
- 【EXTJS】iframe里嵌套ext.window,怎样使ext.window弹出到iframe外,该怎么解决
- Tomcat + extjs 入门有关问题
- extjs ColumnModel 怎么实现表格中的数据小数点对齐
- Extjs 变量前的一个加号代表什么意思?解决方法
- extjs grid 怎么实现 行选中变色
- ExtJs 提交表单的小疑点
- C++ CLI global function 有关问题 分不多了 多谢
- Function(a,b)能在特定情况下直接用Function不带括号和参数表示么?该如何解决
- 自己写的Asp.net Ajax,Jquery,ExtJs 三种Ajax技术框架比较,希望大家提提意见,多谢
- 有updatepanel时,$(function() { 中bind旋钮事件,回发时重复绑定
- 报错 “Cannt assign to a function result”解决方法
- jmail接收邮件报错?This function is not included in this version of jmail.该如何解决
- Process : function (ajaxInfo, processFun)什么意思嘛?解决办法
- jquery接收后台传值出现error: function()异常
- 怎么在程序中模拟页面的javascript:function()交互?内详
- asp2.0 textbox.Attributes.Add("onfocus" "this.value=function()")
- EXTJS grid的getView的refresh步骤报this.grid为空或不是对象
- c#调用MATLAB com组件Undefined function 'armax' for input arguments of type 'iddata'解决思路
- EXTJS grid的getView的refresh方法报this.grid为空或不是对象解决办法