ActionScript 3 Cookbook 中文版 第一章. ActionScript 语言基础

ActionScript 3 Cookbook 中文版

第一章. ActionScript 语言基础
第 1 页 共 34 页
第一章. ActionScript 语言基础
1.0. ActionScript 3.0 Cookbook 概述
1.1. 新建一个 ActionScript 工程
1.2. 自定义应用程序属性
1.3. 在哪里写ActionScript 代码呢
1.4. 如何跟踪信息
1.5. 处理事件
1.6. 响应鼠标和键盘事件
1.7. 算术运算
1.8. 逻辑运算
1.9. 执行条件语句
1.10. 执行复杂的条件语句
1.11. 某段时间重复执行一种操作
1.12. 长时间执行一个任务
1.13. 创建可重用代码
1.14. 增强代码可重用能力
1.15. 从方法中退出
1.16. 获得方法的执行结果
1.17. 处理错误
ActionScript 3 Cookbook 中文版
第一章. ActionScript 语言基础
第 2 页 共 34 页
概述
在Ajax 和 微软 WPF 袭来之前,Macromedia 率先推出基于Flash 的RIA解决方案,用于创建具
有桌面程序富有交互和多功能的Web应用程序,我们称之为“Rich Internet Application”。现在,新
东家 Adobe 更是赋予了Flash超越Web之能力,使之成为完整的开发环境。
除了理论,本书来源于实际ActionScript 应用,超过300 个解决方法用于解决各种编写代码中遇到
的问题。比如:
? 检测用户Flash 播放器版本或操作系统
? 开发自定义类
? 数据和类型格式化
? 字符串的使用
? 开发用户界面组件
? 声音和视频的使用
? 使用Flash Remoting and web services 实现远程过程调用
? 读取,发送和搜索XML数据
? 更多。。。。。。
ActionScript 3 Cookbook 中文版
第一章. ActionScript 语言基础
第 3 页 共 34 页
1.1. 新建一个 ActionScript 工程
问题
运行 Flex Builder 2 然后新建一个ActionScript 工程
解决方法
使用 新建 ActionScript 工程向导来建立你的工程
讨论
一个ActionScript 工程一般至少包含一个class 文件和一个用来放置编译输出的SWF 和HTML 的
bin目录。还包含一些设定来告诉编译器怎么去编译工程。我们只要用向导创建项目,其他的事都交
给Flex Builder 2 维护就行了。有几种方法启动向导,你可以使用菜单中的File ->New->ActionScript
Project, 或者点击左上方的New 按钮,然后从列表中选择 ActionScript Project 。
打开先导后选择 New ActionScript Project ,下一步输入工程名称,比如 ExampleApplication, 当
你创建好工程后,我们会看到主应用程序文件被设置成工程名加上 .as 扩展名。
点击下一步,这里可以添加自定义类,额外的库,或者指定输出目录名称来代替默认的bin 目录,
不过现在我们不必关心这些,点击Finish完成向导。
接着Flex Builder 2 为我们做好了一切。在Navigator 视图上我们看到 ExampleApplication 工程,
包含了一个空的bin 目录和一个ExampleApplication.as 类文件。注意创建的主类文件已经在编辑
视图中打开了,而且在Outline 视图我们看到一个类树型结构,它包含了类方法,属性和import 语
句。
运行我们的程序,只要点击上面的绿色的三角形图标按钮,右边的小虫图标的按钮是调试按钮,两
个命令都是生成.swf 和 html 文件,它会启动浏览器自动运行我们的程序。
到现在我们还没有添加任何语句,这相当于在Flash IDE 中一个空白的 .fla 文件一样, 当运行的时
候除了蓝色的背景什么也没有。
ActionScript 3 Cookbook 中文版
第一章. ActionScript 语言基础
第 4 页 共 34 页
1.2. 自定义应用程序属性
问题
我要改变SWF 的尺寸或背景颜色
解决方法
指定项目属性里的编译器参数或者class文件的 metadata
讨论
不像早期版本的Flash,ActionScript 3.0 编译器真正是一个命令行编译器。你可以通过命令行再加
上一长串参数来创建类或目录,在eclipse 里让这一切变得更简单些。
当建立ActionScript 工程后,默认情况下会生成500x375 尺寸的 .swf, 帧速为24/秒,背景色为蓝
色。我们可以改变这些设定,有几种方法。
第一种方法就是通过ActionScript 编译器参数改变编译器设定。右键点击工程,在菜单中选择
Properties ,然后在左边选择ActionScript Compiler,在右边找到"Additional compiler arguments."
在这里就可以输入参数了,下面是些常见的参数
-default-size width height
-default-background-color color
-default-frame-rate fps
可以这样写:
-default-size 800 600
-default-background-color 0xffffff
-default-frame-rate 31
第一个参数设定输出swf 尺寸为800x600 象素. 第二个参数设定背景色为白色,第三个参数设定播
放帧速为31帧每秒。多个参数可以这样写:
-default-size 800 600 -default-frame-rate 31
第二种方法就是通过类文件种的metadata 来改变设定。Metadata 中包含的语句不会立即被解释,
但是在编译的时候编译会去检测。下面的语句具有等同效果
[SWF(width="800", height="600", backgroundColor="#ffffff", frameRate="31")]
这一行语句放在import 之后,类定义之前,如:
package {
import flash.display.Sprite;
[SWF(width="800", height="600", backgroundColor="#ffffff", frameRate="31")]
public class ExampleApplication extends Sprite
{
public function ExampleApplication()
{
}
}
}
ActionScript 3 Cookbook 中文版
第一章. ActionScript 语言基础
第 5 页 共 34 页
1.3. 在哪里写ActionScript 代码呢
问题
当你有了ActionScript 工程后,接着就需要知道任何输入代码。
解决方法
在类结构中或方法体中添加 ActionScript 代码
讨论
在以前的ActionScript 1.0 和 2.0 中, 有多种途径添加代码:在时间线上,按钮上或电影剪辑上,在
电影剪辑的时间线上通过#include命令引入外部的as文件或class文件。但是 ActionScript 3.0 是
完全基于类的,所以所有的代码都必须放置在类文件中。
当你创建一个新的 ActionScript 工程后,主类文件被自动创建,并且在代码视图中代开了,刚开始
的代码大概是这样的:
package {
import flash.display.Sprite;
public class ExampleApplication extends Sprite
{
public function ExampleApplication( )
{
}
}
}
可能你很熟悉 ActionScript 2.0中的类, 但是3.0 发生了很多变化,这些我们将在第二章讨论,在这
里先学完基础概念先。
首先注意到代码顶层有个关键字 package ,Packages(包) 是用来组织一群相关联的类文件的。
在 ActionScript 2.0, 包是用来判断类文件的路径。在 ActionScript 3.0 中必须指定包,例如,我们
有个utility类包,要这样申明:
package com.as3cb.utils {}
如果你不指明包名,那么该类就输入最顶层的默认包。
接下来,加入 import 语句,引入一个类就相当于在当前的代码文件中创建了使用该类的快捷方式,
这样我们就不需要输入全路径来使用它了。例如,你可以使用下面的 import 语句:
import com.as3cb.utils.StringUtils;
ActionScript 3 Cookbook 中文版
第一章. ActionScript 语言基础
第 6 页 共 34 页
这样我们就可以直接引用 StringUtils 这个类了。从flash.display 引入Sprite 类是因为默认的类文
件继承了Sprite 类。
接下来就看到我们的主类 ExampleApplication,注意到在class 关键字前有个关键字public ,表明
该类是共有的。最后有个公共方法,方法名和主类一样,这种方法称为构造器,当一个类实例被创
建时,其构造器会被自动执行,在这里,当swf 文件被Flash 播放器载入时构造器就会被执行。
In this case, it is executed as soon as the .swf is loaded into the Flash player. So where do you put
your code to get it to execute? Generally, you start out by putting some code in the constructor
method. Here's a very simple example that just draws a bunch of random lines to the screen:
package {
import flash.display.Sprite;
public class ExampleApplication extends Sprite {
public function ExampleApplication( ) {
graphics.lineStyle(1, 0, 1);
for(var i:int=0;i<100;i++) {
graphics.lineTo(Math.random( ) * 400, Math.random( ) * 400);
}
}
}
}
保存然后运行程序,浏览器会打开一个html 文件,显示一个swf 里画了100条随即直线。正如你所
看到的,当swf 被播放器载入后构造器就会被执行。
在这里联系中,我们把代码直接写在了构造器中,但时最好的办法是在构造器中引用一个方法,在
这个方法中添加代码.
对于新手来说,现在你已经学会了如何添加代码了。
ActionScript 3 Cookbook 中文版
第一章. ActionScript 语言基础
第 7 页 共 34 页
1.4. 如何跟踪信息
问题
你需要在运行时跟踪信息或某个数据变量
解决办法
使用 trace 函数,把数据传给它,运行程序,你会发现信息已经在Eclipse的控制台下输出了。
讨论
你可以跟踪一个消息或一个变量的值,也可以输出任何其他数据,就像你在早期的版本中那样,比
如:
trace("Hello, world");
trace(userName);
trace("My name is " + userName + ".");
一旦swf在外部浏览器里运行,就没办法捕获trace输出的信息了,幸运的是Flex Builder2有Console
视图,Console视图就相当于Flash 的Ouput面板。
需要注意的是使用trace 则必须在调试模式下运行程序,这样才能在Console 视图显示数据,下面
的代码创建一个变量,然后赋值,然后用trace输出。
package {
import flash.display.Sprite;
public class ExampleApplication extends Sprite {
public function ExampleApplication( ) {
var userName:String = "Bill Smith";
trace("My name is " + userName + ".");
}
}
}
现在在调试模式下运行程序,运行完关闭浏览器,你会看到在Eclipse下已经输出数据了。
要运行debug 版本的程序,必须要安装debug 版本的Flash 播放器。否则会显示错误信息,另外
debug版本的播放器可以把输出信息到一个文件上,查找mm.cfg文件。一般信息如下:
mm.cfg 文件允许你设置如下变量:
TraceOutputFileEnable 设置值为 0 (不写入文件) 或 1 (写入文件).
TraceOutputFileName 文件路径,如果没有指定,会在mm.cfg 的同目录下生成一个叫flashlog.txt
文件
ErrorReportingEnable 设置值为 0 (不输出错误信息到文件) 或 1 (输出错误信息). 默认为0
MaxWarnings 写入文件的错误信息数量。如果为0 则没有限制。
例子:
TraceOutputFileEnable=1
TraceOutputFileName=C:\flex.log
ActionScript 3 Cookbook 中文版
第一章. ActionScript 语言基础
第 8 页 共 34 页
1.5. 处理事件
问题
我要重复执行某段代码
解决办法
在 enterFrame 事件中添加监听器和关联处理方法
讨论
在ActionScript 2.0 中处理enterFrame 事件是很简单的,你只要创建时间线函数调用
onEnterFrame 然后每次新帧开始时就会自动调用。在 ActionScript 3.0 中有各种各样的事件需要
控制,访问他们也是不难的。
如果你熟悉ActionScript 2.0中的EventDispatcher 类的话,你就很好理解 ActionScript 3.0 事件句
柄了。要广播 enterFrame 事件,你要告诉你的程序去监听这个事件然后指定回调函数。用
addEventListener 方法可以做到:
addEventListener(type:String, listener:Function)
type 参数指出你要监听的事件类型,比如"enterFrame". 然而自己输入这些字符串容易出错,最好
的办法就是调用 Event 类的静态成员属性:导入Event 类,调用addEventListener 方法:
addEventListener(Event.ENTER_FRAME, onEnterFrame);
第二个参数onEnterFrame,指向类中定义的回调函数,该函数需要传递进EVENT 的一个实例:
import flash.events.Event;
private function onEnterFrame(event:Event) {}
event 对象包含一些于该事件有关的信息。这里有个简单的例子:画出一些随机线。
package {
import flash.display.Sprite;
import flash.events.Event;
public class ExampleApplication extends Sprite {
public function ExampleApplication( ) {
graphics.lineStyle(1, 0, 1);
addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
private function onEnterFrame(event:Event):void {
graphics.lineTo(Math.random( ) * 400, Math.random( ) * 400);
}
}
}
ActionScript 3 Cookbook 中文版
第一章. ActionScript 语言基础
第 9 页 共 34 页
1.6. 响应鼠标和键盘事件
问题
我要处理鼠标或键盘事件
解决办法
监听和捕获处理鼠标和键盘事件
讨论
处理鼠标和键盘事件很类似于enterFrame 事件,这些在1.5 节已经讨论过,只是略有不同。对于
鼠标事件,主程序不会直接接收,需要通过一个可视组件监听它(关于可视组件会在第5章讨论)。
下面的例子创建一个sprite,添加到可视组件列,然后在它上面画了个矩形:
package {
import flash.display.Sprite;
import flash.events.MouseEvent;
public class ExampleApplication extends Sprite {
private var _sprite:Sprite;
public function ExampleApplication( ) {
_sprite = new Sprite( );
addChild(_sprite);
_sprite.graphics.beginFill(0xffffff);
_sprite.graphics.drawRect(0, 0, 400, 400);
_sprite.graphics.endFill( );
注意:鼠标事件名称被定义在 MouseEvent 类中,事件处理函数需要传递进一个MouseEvent 类
实例,现在为sprite加入鼠标监听器:
_sprite.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
_sprite.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
}
接着,定义两个处理函数onMouseDown 和 onMouseUp:
private function onMouseDown(event:MouseEvent):void {
_sprite.graphics.lineStyle(1, 0, 1);
_sprite.graphics.moveTo(mouseX, mouseY);
_sprite.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
}
private function onMouseUp(event:MouseEvent):void
{
_sprite.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
}
ActionScript 3 Cookbook 中文版
第一章. ActionScript 语言基础
第 10 页 共 34 页
onMouseDown 方法设置画线的类型,移动画刷到鼠标点击位置,然后添加了第三个鼠标监听器监
听 MouseMove 事件
onMouseUp 方法用removeEventListener 方法移除监听器,它和addEventListener 方法具有相同
语法结构,只是作用相反罢了
最后,定义onMouseMove 函数
private function onMouseMove(event:MouseEvent):void {
_sprite.graphics.lineTo(mouseX, mouseY);
}
}
}
这样就建立了一个事件驱动的绘画程序。
键盘事件的处理简单一些,只需要监听和响应键盘事件,接受这些事件的对象必须出于激活状态。
我们需要在主程序中加入这一行:
stage.focus = this;
下面的例子展示一个简单的类,它监听键盘的 keyDown 事件,输出按键的字符码,
package {
import flash.display.Sprite;
import flash.events.KeyboardEvent;
public class ExampleApplication extends Sprite {
public function ExampleApplication( ) {
stage.focus = this;
addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
}
private function onKeyDown(event:KeyboardEvent):void {
trace("key down: " + event.charCode);
}
}
}
ActionScript 3 Cookbook 中文版
第一章. ActionScript 语言基础
第 11 页 共 34 页
1.7. 算术运算
问题
我要修改一些东西,比如sprite 的角度和位置
解决办法
使用复合赋值运算来改变变量或属性的值
讨论
经常我们需要的新值需要建立在旧值的基础上,比如说,我要移动sprite 到离当前位置向右10个像
素的地方。
一条赋值语句通过赋值操作符(=号)建立,=号右边表达式被运算出来然后其结果存储在左边的变
量或属性中。
// 给变量 quantity 增加6
quantity = quantity + 6;
在这些算术操作中,还有些很便利的复合操作符,如 +=, -=, *=, and /= 会被经常用到。
下面两个语句都是给quantity 加上6:
quantity = quantity + 6;
quantity += 6;
下面两个语句都是给quantity 减去6:
quantity = quantity - 6;
quantity -= 6;
下面两个语句让quantity 乘以 factor:
quantity = quantity * factor;
quantity *= factor;
下面两个语句让 quantity 除以 factor:
quantity = quantity / factor;
quantity /= factor;
如果只是增加1或减少1,还可以象下面这样写
这个语句让quantity 增加1:
quantity++;
下面的两个语句效果相同
quantity += 1;
这个语句让 quantity 减去1:
quantity --;
下面的两个语句效果相同:
quantity = quantity 1;
quantity -= 1;
ActionScript 3 Cookbook 中文版
第一章. ActionScript 语言基础
第 12 页 共 34 页
自增和自减运算符还有前缀写法:
var quantity:Number = 5;
trace(quantity++); // Displays: 5
trace(quantity); // Displays: 6
var quantity:Number = 5;
trace(++quantity); // Displays: 6
trace(quantity); // Displays: 6
回到起初的问题,你可以用这些操作符修改属性值。下面的代码指定了sprite每帧角度加5:
private function onEnterFrame(event:Event) {
_sprite.rotation += 5;
}
ActionScript 3 Cookbook 中文版
第一章. ActionScript 语言基础
第 13 页 共 34 页
1.8. 逻辑运算
问题
我想检测两个值的大小
解决办法
使用==号来比较两个值,使用 isNaN( ) 来检测是否是有效值.
讨论
==号表达式总是返回布尔值来表示两个值是否相等。当两个数类型不同时,比较时会自动转换为相
同的类型再进行比较,如字符型的6和数字型的6比较的话被认为相等。
trace(5 == 6); // : false
trace(6 == 6); // : true
trace(6 == "6"); // : true
trace(5 == "6"); // : false
默认的工程项目,在运行上面的代码会出错。因为编译器被设置为强类型编译检测。关掉强类型检
测,会把数字型转换为字符型,然后再进行比较。一般不推荐关闭强类型检测,这样可能会引发一些
隐蔽的错误不利于程序稳定。
当两个数值不相等时,!=操作符将返回true,否则为false
trace(5 != 6); // : true
trace(6 != 6); // : false
trace(6 != "6"); // : false
trace(5 != "6"); // : true
同样,只有在关闭强类型检测后才能编译通过。
平时要注意不要把==写成=,否则会出现无法预料的错误。比如:
var quantity:int = 5;
// 下面的代码是错误的,正确应为 if (quantity == 6)
if (quantity = 6) {
trace("Rabbits are bunnies.");
}
trace("quantity is " + quantity); // 输出: quantity is 6
可以使用 is 操作符来检测数据类型
var quantity:int = 5;
if (quantity is int) {
trace("Yippee. It's an integer.");
}
然而有些数值是非法的。下面的代码中quantity 等于 NaN (一个表示无效数字的常数)
var quantity:Number = 15 - "rabbits";
NaN 虽然是无效的数值,但它的数据类型仍属于 Number ,
trace(typeof quantity); // 显示: "number"
ActionScript 3 Cookbook 中文版
第一章. ActionScript 语言基础
第 14 页 共 34 页
所以,为了测试有个number 变量类型不是数字,但又是合法的number,尝试下这么写:
var quantity:Number = 15 - "rabbits";
if (quantity is Number) {
//看起来好像正确,实际上是错误的,因为quantity != NaN 结果被认为都是false
if (quantity != NaN) {
trace("Yippee. It's a number.");
}
}
为了检测一个数字是不合法的,要使用指定的函数isNaN( ) 看下面的例子:
var quantity:Number = 15 - "rabbits";
if (isNaN(quantity)) {
trace("Sorry, that is not a valid number.");
}
如果要检测相反条件,只要取反就可以,比如为了检测一个变量是个合法的number,使用!isNAN( ),
如下:
var quantity:Number = 15 - "rabbits";
if (!isNaN(quantity)) {
trace ("That is a valid number.");
}
当然了你还可以使用<和>比较符号来比较两个值得大小。
trace(5 < 6); // 显示: true
trace(5 > 5); // 显示: false
还有<= 和>= 符号
trace(5 <= 6); // 显示: true
trace(5 >= 5); // 显示: true
ActionScript 数据类型的比较有两个情况。在ActionScript 中,数据类型分为两类:基本类型
(string, number, and Boolean) 和复合类型(object, sprite, and array)。当比较基本类型时,是比较
他们的值,下面的例子中 quantity 和 total 被认为是相等的因为他们包含相同的值6
var quantity:Number = 6;
var total:Number = 6;
trace (quantity == total); // 显示: true
然而,当比较符合数据类型时是通过他们的“引用”来比较。当两个引用所指向的对象完全相同才被认
为是相等的,而不仅仅是对象的内容相同。例如,两个数组包含相同的内容,但是他们却不相等:
// 用相同的内容创建两个数组
var arrayOne:Array = new Array("a", "b", "c");
var arrayTwo:Array = new Array("a", "b", "c");
trace(arrayOne == arrayTwo); // 显示: false
只要当引用指向同一个object, array, 或 sprite 才相等. 例子:
ActionScript 3 Cookbook 中文版
第一章. ActionScript 语言基础
第 15 页 共 34 页
// 创建一个简单的数组
var arrayOne:Array = new Array("a", "b", "c");
// 创建另一个变量指向同一个数组
var arrayTwo:Array = arrayOne;
trace(arrayOne == arrayTwo); // 显示: true
ActionScript 3 Cookbook 中文版
第一章. ActionScript 语言基础
第 16 页 共 34 页
1.9. 执行条件语句
问题
我要当满足某些条件时才执行一些命令
解决办法
使用 if 或 switch 语句
讨论
我们经常需要让代码去有选择性的执行,这时可以使用 ActionScript 中的条件语句 if, switch, 或
三元条件运算符 (? :).
条件语句允许我们做出逻辑判断,某种情况下应该做什么。if 语句是最简单的判断语句,当我们遇
到多个可能的情况要处理,这时用switch更好些。而三元条件运算符是把检测和赋值都放在一行中
搞定,简化操作。
首先我们来看一下if 语句, if 语句以if 关键字开头,接着跟一对括号,括号内为测试表达式,后
面的大括号放入测试表达式成立时要执行的代码。
下面的代码检测 animalName 是否等于"turtle."
if (animalName == "turtle") {
// 如果相等 trace( ) 语句将被执行
trace("Yay! 'Turtle' is the correct answer.");
}
另外还可以加上 else 子句来处理当测试表达式不满足时的情况,要注意的是要看到trace()输出的
信息则必须让程序在debug模式下运行。我们把输出信息放到showMessage( ) 方法里,这样这个
函数就可以被重用了
if (animalName == "turtle") {
// 条件为真则执行
showMessage("Yay! 'Turtle' is the correct answer.");
}
else {
// 条件为假
showMessage("Sorry, you got the question wrong.");
}
还可以加入else if 子句,如果 if 条件为真则跳过 else if 子句,如果为假则继续判断 else if 字句
是否为真
if (animalName == "turtle") {
// 条件为真则执行
showMessage ("Yay! 'Turtle' is the correct answer.");
}
else if (animalName == "dove") {
//animalName == "dove"成立则执行
showMessage ("Sorry, a dove is a bird, not a reptile.");
}
ActionScript 3 Cookbook 中文版
第一章. ActionScript 语言基础
第 17 页 共 34 页
还可以包含更多的 else if 子句,然而这种情况,最好的办法就是采用 switch 语句代替,因为switch
与 if 语句结构更加清晰和简洁。 但在某些特殊场合,用 if 可以达到优化性能的目的。
switch 语句包含三部分:
switch 关键字
每个switch 语句都以switch 关键字开始
测试表达式
测试表达式被括号包围,它的结果将决定执行哪段代码。
switch 语句主体
主体中一般包含多个cases子句或一个default 子句
Case 表达式
case 表达式将和 switch 表达式进行比较,如果相等就执行当前case 的主代码。.
Case 主体y
当所有的case表达式都不等于switch表达式,将执行default 主体。
switch (testExpression) {
case caseExpression:
// case body
case caseExpression:
// case body
default:
// case body
}
例子:
var animalName:String = "dove";
switch (animalName) {
case "turtle":
trace("Yay! 'Turtle' is the correct answer.");
case "dove":
trace("Sorry, a dove is a bird, not a reptile.");
default:
trace("Sorry, try again.");
}
ActionScript 3 Cookbook 中文版
第一章. ActionScript 语言基础
第 18 页 共 34 页
一般情况下,在每个case主体最后都会加上 break 语句,这样执行完就会直接退出switch语句。
var animalName:String = "dove";
// 现在第2个case 主体将被执行
switch (animalName) {
case "turtle":
trace("Yay! 'Turtle' is the correct answer.");
break;
case "dove":
trace("Sorry, a dove is a bird, not a reptile.");
break;
default:
trace("Sorry, try again.");
}
当有多个匹配但是执行代码是一样的,这时可以这么写:
switch (animalName) {
case "turtle":
case "alligator":
case "iguana":
trace("Yay! You named a reptile.");
break;
case "dove":
case "pigeon":
case "cardinal":
trace("Sorry, you specified a bird, not a reptile.");
break;
default:
trace("Sorry, try again.");
}
ActionScript 还支持三元条件运算符 (? :), 它把条件测试和赋值语句都放在一行完成。总共有3 个
操作数,第一个是条件表达式,如果为真,则取第二个操作数为结果,否则去第三个操作数为结果。
varName = (conditional expression) ? valueIfTrue : valueIfFalse;
ActionScript 3 Cookbook 中文版
第一章. ActionScript 语言基础
第 19 页 共 34 页
1.10. 执行复杂的条件语句
问题
我要在多个条件中做出决定
解决办法
可以使用逻辑运算符AND (&&), or (||), 和 NOT (!) 来创建符合条件语句。
讨论
ActionScript中的很多语句都能包含条件表达式。包括 if, while, 和 for 语句,如果测试两个条件都成
立可以使用逻辑运算符 AND , &&, (更多细节请看第14 章):
// 测试今天是否是3月17 号
var current:Date = new Date( );
if (current.getDate( ) == 17 && current.getMonth( ) == 3) {
trace ("Happy Birthday, Bruce!");
}
加入些括号让结构更加清晰:
// Check if today is April 17th.
if ((current.getDate( ) == 17) && (current.getMonth( ) == 3)) {
trace ("Happy Birthday, Bruce!");
}
这里使用了逻辑运算符OR , ||, 来测试是否其中有个条件成立:
// 测试是否是周末
if ((current.getDay( ) == 0) || (current.getDay( ) == 6) ) {
trace ("Why are you working on a weekend?");
}
还可以使用 NOT, !, 来测试条件不是真的:
// 检测名字不是Bruce.
if (!(userName == "Bruce")) {
trace ("This application knows only Bruce's birthday.");
}
上面的例子还可以这么写:
if (userName != "Bruce") {
trace ("This application knows only Bruce's birthday.");
}
ActionScript 3 Cookbook 中文版
第一章. ActionScript 语言基础
第 20 页 共 34 页
任何布尔值或能得出布尔结果的表达式都能作为测试表达式:
// 检测如果sprite 是可见的,则输出信息
if (_sprite.visible) {
trace("The sprite is visible.");
}
NOT 运算符经常被用来检测是否是false:
// 检测如果 sprite 是不可见的,则输出信息:
if (!_sprite.visible) {
trace("The sprite is invisible. Set it to visible before trying this action.");
}
NOT 经常和OR 一起用:
// 检测既不是Bruce 有不是 Joey.
if (!((userName == "Bruce") || (userName == "Joey"))) {
trace ("Sorry, but only Bruce and Joey have access to this application.");
}
ActionScript 3 Cookbook 中文版
第一章. ActionScript 语言基础
第 21 页 共 34 页
1.11. 某段时间重复执行一种操作
问题
我要在单帧里多次执行某个任务
解决办法
在单帧里使用循环语句多次执行某个任务,例如,使用 for 语句:
for (var i:int = 0; i < 10; i++) {
// 显示i.的值
TRace(i);
}
讨论
使用循环语句可以让你的代码更加简洁。容易阅读和维护。既可以用 while 也可以用 for 语句,但
是一般for 语句比较好用。两个循环语句都能达到相同结果,只是 for 语句对于大多数程序员来说
更熟悉些。
原形:
for (initialization; test; update) {
statement body
}
下面的例子输出0到999 的数字:
for (var i:int = 0; i < 1000; i++) {
trace(i);
}
trace ("That's the end.");
多个初始值或步进值可以用逗号分开,初始化多个变量var 关键字只需要使用一次,下面的例子展
示了每次i增加1,j 减小1,然后输出i和j:
for (var i:int = 0, j:int = 10; i < 10; i++, j--) {
trace("i is " + i);
trace("j is " + j);
}
ActionScript 3 Cookbook 中文版
第一章. ActionScript 语言基础
第 22 页 共 34 页
for 语句还可以嵌套,看下面的例子:
for (var i:int = 1; i <= 3; i++) {
for (var j:int = 1; j <= 2; j++) {
trace(i + " X " + j + " = " + (i * j));
}
}
1 X 1 = 1
1 X 2 = 2
2 X 1 = 2
2 X 2 = 4
3 X 1 = 3
3 X 2 = 6
进行多重嵌套的for 语句:
for (var i:int = 1; i <= 3; i++) {
for (var j:int = 1; j <= 3; j++) {
for (var k:int = 1; k <= 3; k++) {
trace(i + " X " + j + " X " + k + " = " + (i * j * k));
}
}
}
许多开发都错误的用 for 语句让sprites运动起来; 比如:
for (var i:int = 0; i < 20; i++) {
_sprite.x += 10;
}
上面的代码让sprite 向右移动200 像素,所有的更新都在同一帧完成,会出现两个问题:第一,场
景每帧更新一次,所以只有最后的更新显示在场景中(导致我们看到好像是直接跳过200像素,而
不是20 步内慢慢移动过去)。第二,即时场景不停更新,但是for 循环只需要几位秒,这样的动画
也太快了。因此正确的做法是把动画放到 enterFrame 事件上执行。
再者若循环的代码执行时间超过15秒,Flash播放器就会提示警告。
ActionScript 3 Cookbook 中文版
第一章. ActionScript 语言基础
第 23 页 共 34 页
1.12. 长时间执行一个任务
问题
我要长时间执行一个任务
解决办法
使用 Timer 类,或者监听 sprite 的 enterFrame 事件
讨论
Timer 类是ActionScript 3.0新增的, 来代替早期的 setInterval( ) 和 setTimeout( ) 函数。当创建
Timer 类的实例时,它会在每个时间间隔激活 timer 事件,你可以在事件之间指定延时,然后就有
足够的时间去激活 Timer 构造器了:
var timer:Timer = new Timer(delay, repeatCount);
使用 addEventListener 来设置一个函数处理这个事件,然后使用timer 的 start( ) 方法启动或
stop( ) 停止它。
Timer 类属于 flash.utils 包,还有 TimerEvent 类在 flash.events 包中,因此需要导入它们:
package {
import flash.display.Sprite;
import flash.events.TimerEvent;
import flash.utils.Timer;
public class ExampleApplication extends Sprite {
private var _PreviousTime:Number = 0;
public function ExampleApplication( ) {
var tTimer:Timer = new Timer(500, 10);
tTimer.addEventListener(TimerEvent.TIMER, onTimer);
tTimer.start( );
}
private function onTimer(event:TimerEvent):void {
trace(flash.utils.getTimer( ) - _PreviousTime);
_PreviousTime = flash.utils.getTimer( );
}
}
}
ActionScript 3 Cookbook 中文版
第一章. ActionScript 语言基础
第 24 页 共 34 页
getTimer( ) 函数已经被移动到flash.utils 包中了。它返回程序开始有到现在的相对时间(微妙)
上个例子中,事件每隔5毫秒激活一次。如果你想模拟setInterval( ) 函数,把重复次数设为0。 stop( )
方法类似于clearInterval( ) 函数,停止定时器.
如果想模拟 setTimeout( ) 函数,设置重复数为1,定时器等到指定时间激活一次事件,然后停止。
Timer 类最好的用处就是创建动画而不依赖于影片帧速。看下面的例子,两个定时器时间间隔分别
为50 微妙和100微妙:
package {
import flash.display.Sprite;
import flash.events.TimerEvent;
import flash.utils.Timer;
public class ExampleApplication extends Sprite {
private var _square:Sprite;
private var _circle:Sprite;
public function ExampleApplication( ) {
// 创建两个图形
_square = new Sprite( );
_square.graphics.beginFill(0xff0000);
_square.graphics.drawRect(0, 0, 100, 100);
_square.graphics.endFill( );
addChild(_square);
_square.x = 100;
_square.y = 50;
_circle = new Sprite( );
_circle.graphics.beginFill(0x0000ff);
_circle.graphics.drawCircle(50, 50, 50);
_circle.graphics.endFill( );
addChild(_circle);
_circle.x = 100;
_circle.y = 200;
// 创建两个定时器,启动
var squareTimer:Timer = new Timer(50, 0);
squareTimer.addEventListener(TimerEvent.TIMER, onSquareTimer);
squareTimer.start( );
var circleTimer:Timer = new Timer(100, 0);
circleTimer.addEventListener(TimerEvent.TIMER, onCircleTimer);
circleTimer.start( );
}
ActionScript 3 Cookbook 中文版
第一章. ActionScript 语言基础
第 25 页 共 34 页
// 定义两个事件句柄
private function onSquareTimer(event:TimerEvent):void {
_square.x++;
}
private function onCircleTimer(event:TimerEvent):void {
_circle.x++;
}
}
}
当然用enterFrame 事件也可以实现的,但Timer 技术更加灵活。
ActionScript 3 Cookbook 中文版
第一章. ActionScript 语言基础
第 26 页 共 34 页
1.13. 创建可重用代码
问题
我要实现代码重用,而不是每次都去复制同样的代码。
解决办法
创建一个方法,然后再需要的地方调用它,类中的函数 我们通常称为方法。
怎样创建类方法:
控制修饰符 function 方法名 ( ):返回数据类型 {
// 代码块
}
调用该方法只要饮用方法名就可以了,比如:
方法名( );
讨论
方法中的代码可以被多次执行。当你需要在不同的时间不同的地方执行同一个任务时就会很有用。
把代码放在方法既便于理解又便于维护,而不用再多个地方修改。
像类变量一样,方法也有访问控制符。修饰符有:
private
只能被自身类访问。
protected
能被自身类实例或子类实例访问,其他类实例不能访问。
internal
可以被所在包中的所有类实例访问。
public
可被任何类访问。
ActionScript 3 Cookbook 中文版
第一章. ActionScript 语言基础
第 27 页 共 34 页
如果都没指定修饰符,默认为internal。下面的代码定义了一个画线方法,然后被调用10 次。
package {
import flash.display.Sprite;
public class ExampleApplication extends Sprite
{
public function ExampleApplication( ) {
for(var i:int=0;i<10;i++) {
drawLine( );
}
}
private function drawLine( ):void {
graphics.lineStyle(1, Math.random( ) * 0xffffff, 1);
graphics.moveTo(Math.random( ) * 400, Math.random( ) * 400);
graphics.lineTo(Math.random( ) * 400, Math.random( ) * 400);
}
}
}
还有种种要的方法类型是静态方法,静态方法不属于类实例,可以通过类直接调用静态方法。比如,
有个类叫ExampleApplication, 定义了静态方法:
public static function showMessage( ):void {
trace("Hello world");
}
可以这样调用:
ExampleApplication.showMessage( );
有些类只有静态方法,Math类就是个例子,注意我们使用Math方法时并没有创建类实例,我们只
是调用了类属性那样调用类方法,比如Math.random( ), Math.round( ), 等等
ActionScript 3 Cookbook 中文版
第一章. ActionScript 语言基础
第 28 页 共 34 页
1.14. 增强代码可重用能力
问题
每次执行的任务都有微小的变化,但我又不想每次都复制那些代码修改一次。
解决办法
给方法传递参数让它适应不同的情况。
private function average (a:Number, b:Number, c:Number):void {
trace("The average is " + (c + b + c)/3);
}
讨论
比如你有个求一系列数的平均数函数average( ) ,你就可以把这些数字作为参数传递给函数去计算,
而不必每次都去重写average( )函数。
通常把参数都列在申明函数的括号内,多个参数用逗号分开。
下面有个简单的带有参数的函数申明:
//定义函数,带有两个参数: a 和 b.
private function average(a:Number, b:Number):Number {
return (a + b)/2;
}
//当函数被调用时,参数被传递进来,比如 5 和 11,
//被传递给了 a 和 b
var averageValue:Number = average(5, 11);
大多数情况下,方法参数的个数可以预料的,但是有些情况下参数的个数是事先不确定的。比如:
如果你想要让average( ) 方法接受任何数量的值,这时可以使用内建的数组,所有的参数都被放入
函数数组中。
// arguments 数组
private function average( ):Number {
var sum:Number = 0;
for (var i:int = 0; i < arguments.length; i++) {
sum += arguments[i];
}
return sum/arguments.length;
}
// 像下面这样传递任意数量的参数:
var average:Number = average (1, 2, 5, 10, 8, 20);
arguments 是一个array对象。
ActionScript 3 Cookbook 中文版
第一章. ActionScript 语言基础
第 29 页 共 34 页
1.15. 从方法中退出
问题
我要从方法中退出
解决办法
方法中的代码被执行完就会自动退出,也可使用return 语句直接退出。
讨论
return 语句将导致方法立即退出,ActionScript 解释器继续执行调用方法的所在位置的下面代码。
方法中return下面的语句将被忽略。
private function sampleFunction ( ):void {
return;
trace("Never called");
}
下面的代码展示如果密码是错误的,则从方法中退出:
private function checkPassword (password:String):void {
// 如果密码不是"SimonSays", 退出方法
if (password != "SimonSays") {
return;
}
//否则执行剩余的代码
showForm ("TreasureMap");
}
// 使用错误的密码调用函数,所以函数退出
checkPassword("MotherMayI");
//使用正确的密码,所以显示“TreasureMap”信息.
checkPassword("SimonSays");
你可能注意到上面的例子方法被申明为void, 如果用return 语句只是简单的退出这时可以的,但如
果想返回值得话编译器就会报错了,如:
private function sampleMethod ( ):void {
return "some value"; // This causes the compiler to generate an error.
}
ActionScript 3 Cookbook 中文版
第一章. ActionScript 语言基础
第 30 页 共 34 页
1.16. 获得方法的执行结果
问题
我想执行一些方法,然后返回结果给调用它的函数
解决办法
使用 return 语句返回结果
讨论
return 返回的数据类型必须与函数申明的返回类型相一致。
private function average (a:Number, b:Number):Number {
return (a + b)/2;
}
现在我们调用 average( ) 方法 然后把返回结果存到变量中,然后使用这个变量:
var playerScore:Number = average(6, 10);
trace("The player's average score is " + playerScore);
也可以不通过变量:
trace("The player's average score is " + average(6, 10));
注意,如果你不处理返回的值,那么返回结果就是丢失掉:
average(6, 10);
ActionScript 3 Cookbook 中文版
第一章. ActionScript 语言基础
第 31 页 共 34 页
1.17. 处理错误
问题
我想让程序自己检测和处理遇到的错误。
解决办法
当检测到错误时使用 throw 语句抛出异常。把可能出现错误的代码都放到 try 块中,然后在catch
块中进行错误处理。
讨论
Flash 播放器 8.5 开始支持 try/catch 方法来处理错误。这意味着可以灵活的处理遇到的错误了。
除了语法错误(这时编译器就通不过),其他类型的错误如非法数据等都可以自己处理。
处理异常包括两个部分,抛出异常和捕获异常。有些异常系统会自动抛出,比如 IllegalOperationError,
MemoryError, 和 ScriptTimeoutError. 它们都在 flash.errors 包中。除了系统定义的错误外也可以
抛出自定义错误,然后捕获它进行处理。使用 throw 语句抛出一个Error 对象或Error 子类实例,
比如:
throw new Error("A general error occurred.");
正如我们看到的,Error 构造器接受一个参数,这个信息和这个错误相关联。这个参数是可选的,
依赖于你怎样处理这个错误,你可以不使用,但是大多数情况下都指定一个错误信息作为调试目的。
一旦异常被抛出,Flash 就会暂停当前进程去寻找 catch 块去处理异常。任何有潜在错误的代码都
要放在 try 块中,如果异常抛出,只有它所在的 try 块被暂停,然后相关联的 catch 块被调用,看
下面的例子:
try {
trace("This code is about to throw an error.");
throw new Error("A general error occurred.");
trace("This line won't run");
}
catch (errObject:Error) {
trace("The catch block has been called.");
trace("The message is: " + errObject.message);
}
上面的代码数出以下信息:
This code is about to throw an error.
The catch block has been called.
The message is: A general error occurred.
ActionScript 3 Cookbook 中文版
第一章. ActionScript 语言基础
第 32 页 共 34 页
当然,上面的代码还是过于简单,但是这是个基本框架,可以看到只要抛出异常,try 块就会退出,
catch 块被执行,传递了一个 Error 对象给 catch.
更多情况下,异常是从函数或方法中抛出的,Flash 会检测该函数是否在 try 块内被调用,如果是,
则调用相应的 catch 块。
private function displayMessage(message:String):void {
if(message == undefined) {
throw new Error("No message was defined.");
}
trace(message);
}
try {
trace("This code is about to throw an error.");
displayMessage( );
trace("This line won't run");
}
catch (errObject:Error) {
trace("The catch block has been called.");
trace("The message is: " + errObject.message);
}
上面的代码输出以下内容:
This code is about to throw an error.
The catch block has been called.
The message is: No message was defined.
如果你不肯定你的函数或方法会在何时或如何抛出异常,这时就应该在try块进行调用。
// 定一个在指定的sprite里的画矩形函数。
private function drawRectangle(sprite:Sprite, newWidth:Number, newHeight:Number):void {
// 检测长和宽的数值是否合法,否则抛出异常。
if(isNaN(newWidth) || isNaN(newHeight)) {
throw new Error("Invalid dimensions specified.");
}
// 如无异常,则画出矩形
sprite.graphics.lineStyle(1, 0, 1);
sprite.graphics.lineTo(nWidth, 0);
sprite.graphics.lineTo(nWidth, nHeight);
sprite.graphics.lineTo(0, nHeight);
sprite.graphics.lineTo(0, 0);
}
ActionScript 3 Cookbook 中文版
第一章. ActionScript 语言基础
第 33 页 共 34 页
现在我们在 try/catch 语句内调用该函数。
try {
drawRectangle(this, widthB, heightB);
}
catch(errObject:Error) {
this.graphics.clear( );
tOutput.text = "An error occurred: " + errObject.message;
}
另外对于try/catch 语句,还可以加入 finally 块,finally 块包含的代码无论是否遇到异常都会被执
行。例如下面的两个例子效果相同:
//没有使用finally:
private function displayMessage(message:String):void {
try {
if(message == undefined) {
throw new Error("The message is undefined.");
}
trace(message);
}
catch (errObject:Error) {
trace(errObject.message);
}
trace("This is the last line displayed.");
}
//使用 finally:
private function displayMessage(message:String):void {
try {
if(message == undefined) {
throw new Error("The message is undefined.");
}
trace(message);
}
catch (errObject:Error) {
trace(errObject.message);
}
finally {
trace("This is the last line displayed.");
}
}
ActionScript 3 Cookbook 中文版
第一章. ActionScript 语言基础
第 34 页 共 34 页
如果在catch 中使用了return语句,那结果就不一样了:
//没有使用finally:
private function displayMessage(message:String):void {
try {
if(message == undefined) {
throw new Error("The message is undefined.");
}
trace(message);
}
catch (errObject:Error) {
trace(errObject.message);
return;
}
// 这一句没有执行.
trace("This is the last line displayed.");
}
//使用 finally:
private function displayMessage(message:String):void {
try {
if(message == undefined) {
throw new Error("The message is undefined.");
}
trace(message);
}
catch (errObject:Error) {
trace(errObject.message);
return;
}
finally {
// 执行,不管是否有异常发生。
trace("This is the last line displayed.");
}
}
通过这一节的学习,现在你可以建立复杂的异常处理系统。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值