ExtJs —— Function

OK,这个类也在Ext包的外围,按理来说应该是跟标准的JS函数有点瓜葛。不过详细看了看Spket提供的函数,基本上跟JS的是很不一样。但是按照文 档说的,这个Function中的函数对每个JS的function都有效。估计还是从那里继承过来的。不过我没做详细的源码阅读,也不敢随便下结论。

还是看看这个函数有什么东西在里面把。

createCallback ,用这个函数对象创建一个回调,说白了,让Function类自己调用自己,并且可以对自己传递参数,听起来很别扭。不过给个例子就明白了。
var sayHi = function(name){
alert('Hi, ' + name);
}   

// clicking the button alerts "Hi, Fred"
new Ext.Button({
text : 'Say Hi',
renderTo : document.body,
handler : sayHi.createCallback('Fred')
});
以上创建了一个按钮,并且为按钮handler添加了一个函数叫做sayHi。不过这里有点特别,sayHi这个函数定义的时候有个参数,那么因为我们需 要按按钮的时候调用sayHi并且向其传递一个参数,所以这里对sayHi弄了一个回调函数,并且传递了一个Fred,那么每次点击按钮的时候就会 alert一个"hi, Fred",就是这样。自己调用了自己。

要注意的是,这个创建的回调作用范围是在窗口范围内的。如果要创建在其他作用范围内的回调,需要用创建代理的方法,而不是这个。

OK,下面还有个需要注意的地方就是,如果我们把代码改成这样子,会有怎样的效果呢?
Ext.onReady(init);

function init() {
new Ext.Button({
text : 'Say Hi',
renderTo : document.body,
handler : sayHi('fred')
});
}

function sayHi(name){
alert('Hi, ' + name);
}

试验之后发现,在页面一完成载入的时候,就直接调用了sayHi方法!更准确的说,是在完成对代码解析之后,就直接调用了。如果不希望这样,那么就还是改 成回调的方式吧。通过两个例子看出来,创建回调,就是在需要的时候把方法对象当成一个变量,进行方法调用。而后者则是直接调用该方法。

createDelegate( [Object obj], [Array args], [Boolean/Number appendArgs] ) : Function , 这个熟悉C#的人都不会陌生吧。有时候,我们需要把同一个方法用在不同的执行者身上,这种时候就需要代理,从而让一个方法因为执行者的不同而表现出不同的 行为。此时,函数执行的上下文(scope也叫做作用范围),就是我们的执行者(代理人),通常我们用this表征我们的代理。好吧,我们看看例子:

var sayHi = function(name){
alert('Hi, ' + name + '. You clicked the "' + this.text + '" button.');
}

var btn = new Ext.Button({
text: 'Say Hi',
renderTo: Ext.getBody()
});

btn.on('click', sayHi.createDelegate(btn, ['Fred']));

关注两个地方。一个事sayHi这个函数对象所指向的函数,这里面出了一个this.text。究竟这个this指的是谁?之后我们看下 文,btn.on,这里on就是给按钮的一个事件注册一个处理函数。这里我们为click也就是单击事件注册(关于ExtJs的事件机制我们以后会说 的)。不过注册时候,用了createDelegate这个方法,并且传递了两个参数给它,一个是btn,另外一个是JSON数组,里面就一个元素。这个 跟我们的function(name)定义不符合!但是它确实能够调用,这是为什么呢?这里第一个参数就是代理,换句话说是把这个函数追加到哪个上下文对 象上去。例子中是btn,就可以理解为把sayHi这个函数追加给了btn,这样btn自己就有了一个新的函数叫做sayHi,在单击它的时候,btn调 用了“自己”的函数sayHi。所以sayHi中的this.text,所指向的就是btn,那么得到的文本自然是"Say Hi"了~

回头看这个方法的三个参数。第一个是代理的上下文对象,现在好理解了。第二个是参数数组,根据你定义的方法的参数个数可以自己定。第三个参数args既可 以是布尔型又可以是数字型。什么意思呢?如果是boolean型的true,当我们调用方法时 ['Fred']会被当成一个对象传入的,而不是当成里面存的值。我们可以把它写成true(btn.on('click', sayHi.createDelegate(btn, ['Fred'],true)); ), 这个时候alert输出的不是Fred而是[object Object],改成false的时候就跟不加它是一样的。如果是数字呢,那么args中的参数会被替换到数字所指明的位置上。假设那个函数有两个参数, 我们在后面加了一个2,那么第二个参数就会是Fred了。注意了,这个参数的位置,跟数组一样,是从0开始,也就是说1表示了第二个参数!

createInterceptor( Function fcn, [Object scope] ) : Function , 这个函数也是非常有意思的,以后会在Obserable中经常遇到,可以说很多事件机制里面都有它的影子(er,也可以说是幽灵,呵呵)。什么意思呢?它 创建一个拦截器(Struts2,阿弥陀佛)。被传入的参数函数fcn会在原始函数调用之前被调用。如果fcn返回一个false,那么很抱歉,原始函数 也执行不能了。只有fcn返回true的时候才会执行原来的函数。这个创建拦截器所/返回的/函数对象的/返回值/是原始函数的返回值。并且所创建的拦截 器函数也必须跟原始函数有一样的参数。很多时候是验证原来函数的输入而无须改写原有函数。看例子吧:
var sayHi = function(name){
alert('Hi, ' + name);
}

sayHi('Fred'); // alerts "Hi, Fred"

// 这里创建了一个新的函数,验证了原来函数的输入而无须改写原有函数。
var sayHiToFriend = sayHi.createInterceptor(function(name){
return name == 'Brian';
});

sayHiToFriend('Fred'); // no alert
sayHiToFriend('Brian'); // alerts "Hi, Brian"

开始还能alert一个Fred,后来因为加了拦截器函数,验证输入,如果是等于Brian才返回true,所以原来的函数,只有在它的输入时Brian的时候才能被调用。也就是说第二个alert Fred是不能被调用的。

这个函数的第二个函数是fcn的作用范围,默认是原始函数的作用范围或者window。

createSequence( Function fcn, [Object scope] ) : Function,这个函数的作用是让原始函数和参数函数fcn的调用顺序进行合并。此方法所返回函数的返回值跟原函数的返回值是一样的。并且fcn必须 使用原函数的参数进行调用,看例子:

var sayHi = function(name){
alert('Hi, ' + name);
}

sayHi('Fred'); // alerts "Hi, Fred"

var sayGoodbye = sayHi.createSequence(function(name){
alert('Bye, ' + name);
});

sayGoodbye('Fred'); // both alerts show

原函数是像Fred问候,创建的fcn是跟他说拜拜。结果用原函数创建了一个调用顺序合并的函数,结果就是sayGoodbye函数会一次调用原函数(sayHi)和fcn所表示的函数。最后调用sayGoodbye的时候会以此输出hi和goodbye给Fred。

第二个参数是作用范围,跟前面的说明是一样的。

defer( Number millis, [Object obj], [Array args], [Boolean/Number appendArgs] ) : Number , 这个函数的参数可老长了。看名字就知道,是推迟的意思。那么估计第一个参数就是推迟的时间了,millis,莫非是毫秒级;第二个参数应该指代的大概是作 用范围吧;那么第三个参数args,顾名思义应该是传递给原函数的参数;最后一个appendArgs,这不跟前面的代理的那个参数一样么?对滴,文档上 说的跟我说的一样(-_-b)。就是这个意思。看例子吧:
var sayHi = function(name){
alert('Hi, ' + name);
}

sayHi('Fred');

sayHi.defer(2000, this, ['Fred']);

(function(){
alert('Anonymous');
}).defer(100);

第一个立即执行(不是死刑啊)。第二个sayHi其实是最后执行,因为它推迟了两秒。最后一个是匿名函数,推迟0.1秒执行。

这个函数的返回值,是一个timeout的id,可以用来清除timeout的。怎么用?阿弥陀佛,看JS,最原始的JS,clearTimeout可是 window对象的基本方法之一啊。window.clearTimeout()方法所用的参数就是一个id,用来清除注册给setTimout的方法。 而defer方法返回的就是被注册的id。如果需要取消推迟执行,可以记录这个id并且使用window的clearTimout来取消。

好,最后看看还有没有我们疏忽的东西。发现Function类有四个属性,name, length, arity和arguments,有些可以顾名思义,有的不成。看来还真得找个DHTML手册看看。另外apply方法,以后在讲Ext这个核心类的时候 会涉及到,所以这里就先放过吧。

咦?还有个call方法。不需要说了吧就是调用函数对象啊。看代码:
var sayHi = function(name){
alert('Hi, ' + name + " " + this.name);
}
sayHi.call(sayHi, ['fred','gray']);

前一个是上下文对象,后面是参数。输出是hi, fred,gray undefined。可见,参数是解析数组内容的。如果有兴趣,试试JSON对象吧,例如说{he:"hey"}.he。再试试变参。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值