http://blog.csdn.net/Begin_Game/archive/2008/10/15/3081317.aspx
一:for each ... in与 for..in 一样都是自动遍历对象的属性,不同的是for each...in 更像是为遍历保存键值对的集合而产生的,而这些集合的类型可以是未声明类型的对象,甚至XML文件,而在遍历时循环中的循环变量类型声明是用"*"号来表示,意为任意类型。1:遍历未声明类型对象:var arr:Object = {1:"jack",2:2046};for each(var i:* in arr){ trace(i);}/-----jack2046

2:遍历XML:
var xml:XML = <beans>
    <bean>jack</bean>
    <bean>2046</bean>
     </beans>;
for each(var item:* in xml.bean)
{
 trace(item);
}
/-----
jack
2046

二:break的特殊用法:
在AS3中,由于其作用于动画的特殊性,孕生出很有意思的的label标签用法。此label标签不能独立存在,必须依赖break、continue两个跳转关键字进行使用。
gotoout:for(var i:int = 0; i < 10; i++)
  {   
   for(var j:int = 0; j < 10; j++)
   {
    trace("i:" + i + ",j:" + j);
    if((i==0)&& (j==8)){
     break gotoout;
    }
   }   
  }
/-----
i:0,j:0
i:0,j:1
i:0,j:2
i:0,j:3
i:0,j:4
i:0,j:5
i:0,j:6
i:0,j:7
i:0,j:8

在这里gotoout标签包含了一个嵌套for循环,之中退出条件为 i=0 && j==8 时,则跳转出整个循环;如换为continue则为:
gotoout:for(var i:int = 0; i < 10; i++)
  {   
   for(var j:int = 0; j < 10; j++)
   {    
    if((i==0)&& (j==8)){
     trace("跳过第i:" + i + "  j:" + j +"次循环");
     continue gotoout;
    }
    else
    {
     trace("i:" + i + ",j:" + j);
    }
   }
   if((i==1))
   {
    break;
   }
  }
/---------
i:0,j:0
i:0,j:1
i:0,j:2
i:0,j:3
i:0,j:4
i:0,j:5
i:0,j:6
i:0,j:7
跳过第i:0  j:8次循环
i:1,j:0
i:1,j:1
i:1,j:2
i:1,j:3
i:1,j:4
i:1,j:5
i:1,j:6
i:1,j:7
i:1,j:8
i:1,j:9

当然也不一定是循环才能使用breank,但continue一定要配合循环使用
break:
trace("1");
gotoout:{
 trace("2");
 trace("3");
 break gotoout;
 trace("4");
 trace("5");
}
/-------
trace("1");
gotoout:{
 trace("2");
 trace("3");
 break gotoout;
 trace("4");
 trace("5");
}

continue:
trace("1");
gotoout:{
 trace("2");
 trace("3");
 continue gotoout;
 trace("4");
 trace("5");
}
/-------
1039: 找不到 continue 语句的目标。

标签也可嵌套使用,但无论嵌套几层,最终跳出哪层标签由 break 标签名 决定的
trace("1");
gotoout:{
 gotoout1:{
  gotoout2:{
   trace("2");
   trace("3");
   break gotoout2;
   trace("4");
   trace("5");
  }
  trace("gotoout1");
 }
 trace("gotoout");
}
/------
1
2
3
gotoout1
gotoout

如break gotoout2 换成 break gotoout ,则程序会直接跳出gotoout标签,不会打印 gotoout1、gotoout。

三:局部变量可当全局变量使用
AS3的代码编译是提交给Flash Play优化后编译,因此会出现在java和C++中不可想象的状况。
for(var i:int =1; i<=3; i++)
{
 var str:String = "你好,正在循环";
 trace(i + ":循环内:" + str);
}
trace("循环外:" + str);
/-----
1:循环内:你好,正在循环
2:循环内:你好,正在循环
3:循环内:你好,正在循环
循环外:你好,正在循环

可以看到str是在for循环开始后在循环内部声明并赋值的,但在循环结束后在循环外部依然正常使用了str这个变量,这是由于代码在编译过程中编译器将声明前置优化了。
var str:String;
.......

因此无论将var str:String 放在代码块的何处,编译器总会将变量声明优化前置。但为了程序的可维护性,最好还是按照java、C++等语言的严谨写法书写代码。
局部变量虽可随处声明,但注意其赋值的有效性,如:
trace("循环外:" + str);
for(var i:int =1; i<=3; i++)
{
 var str:String = "你好,正在循环";
 trace(i + ":循环内:" + str);
}
/-----
循环外:null
1:循环内:你好,正在循环
2:循环内:你好,正在循环
3:循环内:你好,正在循环

程序在变量未赋值前就使用此变量,虽可编译运行,但最终打印出str的值为null。

四:函数表达式
这一点很像js的匿名函数,可以说完全相同。
var func:Function = function(par:int){
 return par*8;
}
trace(func(8));
/-------
64

声明了类型为Function名为func的变量,此变量的值很怪异,看上去完全是个函数,其实函数本身也是对象,把对象赋值给变量有什么不对呢?虽然java有匿名类、C#也引入了匿名函数,但它们因为的实现方式肯定没有js与as3直观和简洁。匿名函数是由变量记录这个无名函数的内存地址,而外部访问是由变量作为介质的,因此删除变量,等于删除了这个无名函数。但值得注意的是,函数表达式本身的书写方式导致不宜维护,因此如果没有特别需要毋须将函数写为匿名函数。

五:arguments
AS3函数使用中,可以给函数传入一系列的参数,如:
function sub(par1:int,par2:int)
{
.....
}
在这之中,当参数传入函数调用之后,AS3编译器会生成一个名为arguments数组对象,它保存了当前函数传入的参数的值,可以看作参入参数的备份。
function sub(par1:int,par2:int)
{
 par1 = 3;
 par2 = 4;
 var sub1:int = par1 + par2;
 var sub2:int = arguments[0] + arguments[1];
 trace("函数参数之和:" + sub1);
 trace("arguments之和:" + sub2);
}
sub(1,2);
/--------
函数参数之和:7
arguments之和:3

但这个备份数组仅限于参数是按值传递的情况下,如参数是以引用传递则arguments的值会跟着改变。
function sub(par:Array)
{
 par[0] = "jack";
 trace("函数参数:" + par);
 trace("arguments:" + arguments);
}
var arr:Array = new Array(1,2,3);
sub(arr);
/--------
函数参数:jack,2,3
arguments:jack,2,3

另外,arguments有个重要属性:callee,就是call自己。如使用该属性,程序会将arguments所在的当前函数按照callee的赋值再次执行一次
var bool:Boolean = true;
function sub(par:Array)
{
 par[0] = "jack";
 trace("函数参数:" + par);
 trace("arguments:" + arguments);
 if(bool)
 {
  bool = false;
  var arrbak:Array = new Array("开始执行callee",1,1);
  trace("开始执行callee");
  arguments.callee(arrbak);
 }
}
var arr:Array = new Array(1,2,3);
sub(arr);
/--------
函数参数:jack,2,3
arguments:jack,2,3
开始执行callee
函数参数:jack,1,1
arguments:jack,1,1

 

六、重载

一种OOP语言拥有重载特性是很习以为常的事,毕竟任何OOP语言都必须遵循OOP三大特质。有意思的是AS中,重载这样在其他语言司空见惯的特性,在AS3出现以前都是不存在的(不仅AS,javascript、vbScript、ruby等常见脚本语言都不支持,到底是脚本啊 .... ),且AS3的重载说到底也是模拟重载,一种数组变通而已。

1:使用aruments的length属性进行重载

function test(par1:int):void
{
 if(arguments.length == 1)
  trace("重载1");
 else if(arguments.length >1)
  trace("重载2");
 else
  trace("重载3");
}
test(1);
test(1,2);
test(1,2,3);

/--------------------

重载1
重载2
重载2

注意函数test在声明时只声明了 par1:int 一个参数,而在调用时程序连续调用了3次test,并且后两次参数与函数声明不符,多了。但编译器如果运行在标准模式下编译,是不会报错也可以运行的,这样arguments数组会扩大为你传进来参数的个数,如test(1,2,3),arguments长度就是3了,程序中如果需要用到2、3,只能通过arguments[1]/[2]来找到多出的参数。用arguments时,注意编译器一定要运行在标准模式下;参数只能比函数声明多,不能少。

 

2:使用 ...(args) 来传入不同参数。

注意:...(args) ,前面是3点,英文模式下的3点,不多不少。args是传进来参数数组的名称,可以任意。

function test(...args):void
{
 if(args.length == 1)
  trace("重载1");
 else if(args.length >1)
  trace("重载2");
 else
  trace("重载3");
}
test(1);
test(1,2);
test(1,2,3);

/--------------------

重载1
重载2
重载2

 

当使用...args ,在程序中就不能用arguments来获取参数了,取而代之是args。...args 也可以与声明参数一起使用

function test(par1:int,...args):void
{
 if(args.length == 1)
  trace("参数" + par1 + "  重载1  args参数:" + args);
 else if(args.length == 2)
  trace("参数" + par1 + "  重载2  args参数:" + args);
 else
  trace("参数" + par1 + "  重载3  args参数:" + args);
}
test(1,1);
test(1,2,3);
test(1,2,3,4,5);

/---------------------

参数1  重载1  args参数:1
参数1  重载2  args参数:2,3
参数1  重载3  args参数:2,3,4,5

这样也变通模拟了函数重载,args是不需要编译器标准的无论在严谨或标准模式都可运行;args使用后arguments不能使用包括其属性;在给已声明参数赋值后,接下来无论多少个参数编译器都会将其作为数组传给args。

posted on 2009-12-05 04:50  sungo  阅读(359)  评论(2编辑  收藏  举报