as3:Function以及call,apply

本文对比分析了AS3和C#中委托与方法调用的区别,详细介绍了如何在AS3中使用Function类实现类似C#委托的功能,并通过示例展示了如何在AS3中灵活地调用不同方法,以及利用Function类的call()与apply()方法改变函数执行时的this指针指向。


作者:菩提树下的杨过
出处:http://yjmyzz.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

Function类在as3中是直接从Object继承下来的,通常开发者定义的每一个function,均可以认为是Function类的一个实例。 

如果硬要跟c#做比较,Function类跟Delegate(委托)有几分相似,均可以达到通过该类型的实例来调用不同方法的目的。 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
using System;
 
namespace FunctionTest
{
     class Program
     {
         private delegate void _delegateType( string name);
 
         static void Main( string [] args)
         {
             _delegateType d = new _delegateType(helloWorld);
             d( "jimmy.yang" );
 
             Console.Read();
         }
 
         private static void helloWorld( string name) {
             Console.WriteLine( "hello,{0}!" , name);
         }
     }
}

这段c#代码中,委托_delegateType的实例d,最终调用了具有同样方法签名的方法helloWorld.

来看下as3是怎么做的?

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
package
{
     import flash.display.Sprite;
     import flash.events.Event;
 
     public class FunctionTest extends Sprite
     {
         private var _delegate:Function ;
         
         public function FunctionTest()
         {
             if (stage){init();}
             else {
                 this .addEventListener(Event.ADDED_TO_STAGE,init);
             }
         }
         
         private function init(e:Event= null ): void {
             this .removeEventListener(Event.ADDED_TO_STAGE,init);           
             this ._delegate = this .helloWorld;
             _delegate( "菩提树下的杨过" ); //hello, jimmy.yang ! 即:相当于c#中"委托"调用"方法"
             
             var jimmy: Object = new Object ();
             //定义jimmy对象的一个方法
             jimmy.addSalary = function (addSalary: uint ): void {
                 trace ( "姓名:" , this .name, ",原工资:" , this .salary, ",新工资:" , this .salary + addSalary);
             };
             
             trace (jimmy.addSalary is Function); //true
             trace ( typeof jimmy.addSalary); //function
             
             jimmy.name = "jimmy.yang" ;
             jimmy.salary = 3000 ;
             jimmy.addSalary( 500 ); //姓名: jimmy.yang ,原工资: 3000 ,新工资: 3500
             
             
             var mike: Object = new Object ();
             mike.name = "Mike" ;
             mike.salary = 5000 ;
             jimmy.addSalary.call(jimmy, 1000 ); //姓名: jimmy.yang ,原工资: 3000 ,新工资: 4000
             jimmy.addSalary.call(mike, 1000 ); //姓名: Mike ,原工资: 5000 ,新工资: 6000   
             jimmy.addSalary.apply(mike,[ 1100 ]); //姓名: Mike ,原工资: 5000 ,新工资: 6100    
             
             
             _delegate = jimmy.addSalary;
             _delegate.call(mike, 1999 ); //姓名: Mike ,原工资: 5000 ,新工资: 6999
             _delegate.apply(mike,[ 2999 ]); //姓名: Mike ,原工资: 5000 ,新工资: 7999
             
             
         }
         
         private function helloWorld(name: String ): void {
             trace ( "hello," ,name, "!" );
         }
         
         
     }
}

哦,代码有点长,先不用全看完,注意:

?
1
2
this ._delegate = this .helloWorld;
_delegate( "菩提树下的杨过" ); //hello, jimmy.yang ! 即:相当于c#中"委托"调用"方法"

这不正是c#中委托调用方法的翻版吗?但即使都当作"委托"来用,也有明显的区别:as3中不用强制定义“委托”的方法签名。

 

再来看看另外Function类的重要方法call()与apply()

我们知道,每个function最终在执行时,都要有一个上下文环境,也就是this指针在函数执行时,到底指向谁的问题?

?
1
2
3
4
5
var jimmy: Object = new Object ();
//定义jimmy对象的一个方法
jimmy.addSalary = function (addSalary: uint ): void {
     trace ( "姓名:" , this .name, ",原工资:" , this .salary, ",新工资:" , this .salary + addSalary);
};

这里我们动态的给jimmy对象定义了一个addSalary方法,注意addSalary方法体中的this,如果我们用

?
1
2
3
jimmy.name = "jimmy.yang" ;
jimmy.salary = 3000 ;
jimmy.addSalary( 500 ); //姓名: jimmy.yang ,原工资: 3000 ,新工资: 3500

这样调用时,this指针默认就是指向jimmy的,所以this.name自然就是jimmy.yang,而this.salary自然也就是3000,这不废话么?

但是我们可以借助Function类的apply以及call方法,显式改变this指针的指向!注意上面代码中的这一部分:

?
1
2
3
4
5
var mike: Object = new Object ();
mike.name = "Mike" ;
mike.salary = 5000 ;
jimmy.addSalary.call(jimmy, 1000 ); //姓名: jimmy.yang ,原工资: 3000 ,新工资: 4000
jimmy.addSalary.call(mike, 1000 ); //姓名: Mike ,原工资: 5000 ,新工资: 6000   

这里我们又搞出了一个mike对象,而且并没有给他定义addSalary方法,但如果系统也要给mike同志临时加工资怎么办? 可以把jimmy对象的addSalary方法应用在mike身上,即jimmy.addSalary.call(mike,1000),最终mike得偿所愿,在原工资5000的基础上加了1000,就成了工资6000 (如果现实中加工资也这么容易就好了)

至于apply方法,作用跟call一样,也可以用来改变函数执行时,this指针的指向,区别在于apply方法要求第二个参数必须是数组形式,即:

jimmy.addSalary.apply(mike,[1100]);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值