Flex 入门


阅几科技 Flex 入门 阅几科技 本文档为阅几科技有限公司内部资料,仅为内部人员查阅,谢绝任 何形式的转载。 - 1 - 阅几科技 - 2 - 版本号 编写者 日期 备注 V1.0 sure 2010/6/1 创建 阅几科技 - 3 - 目录 1.1 Flex简介 ................................................................................................................................- 5 - 1.1.1 为了迎合更多的developers(开发者)。................................................................. - 5 - 1.1.2 为了一个标准。........................................................................................................ - 5 - 1.2 ActionScript3 的特点 ............................................................................................................ - 5 - 1.2.1 文本编辑.................................................................................................................... - 5 - 1.2.2 ActionScript3 与JavaScript之间的差异..................................................................... - 6 - 1.2.3 数据类型.................................................................................................................... - 6 - 1.2.4 点语法........................................................................................................................ - 6 - 1.2.5 用户定义函数............................................................................................................ - 6 - 1.2.6 本地变量.................................................................................................................... - 6 - 1.2.7 预定义对象................................................................................................................ - 7 - 1.2.8 剪辑动作.................................................................................................................... - 7 - 1.2.9 调试器........................................................................................................................ - 7 - 1.2.10 提供 上下文敏感帮助.............................................................................................. - 7 - 1.2.11 XML支持.................................................................................................................. - 7 - 1.3 MXML介绍 ........................................................................................................................... - 7 - 1.4 Flex Builder 3......................................................................................................................... - 8 - 1.4.1 先new一个FlexProject项目....................................................................................... - 9 - 1.4.2 工程命名.................................................................................................................. - 10 - 1.4.3 完成New Project后,出现如下界面...................................................................... - 10 - 1.4.4 点击Design,出现如下界面 .................................................................................. - 11 - 1.4.5 然后直接选择如下界面的label放到背景板上 ...................................................... - 11 - 1.4.6 运行.......................................................................................................................... - 13 - 1.5 编程基础............................................................................................................................. - 13 - 1.5.1 数据类型.................................................................................................................. - 13 - 1.5.2 关于语法.................................................................................................................. - 14 - 1.5.2.1 区分大小写................................................................................................... - 14 - 1.5.2.2 点语法........................................................................................................... - 14 - 1.5.2.3 斜杠语法....................................................................................................... - 15 - 1.5.2.4 分号............................................................................................................... - 15 - 1.5.2.5 小括号........................................................................................................... - 16 - 1.5.2.6 注释............................................................................................................... - 16 - 1.5.2.7 关键字和保留字........................................................................................... - 16 - 1.5.2.8 常量............................................................................................................... - 17 - 1.5.3 运算符...................................................................................................................... - 18 - 1.5.3.1 运算符的优先级和结合律........................................................................... - 19 - 1.5.3.2 主要运算符................................................................................................... - 20 - 1.5.3.3 后缀运算符................................................................................................... - 20 - 1.5.3.4 一元运算符................................................................................................... - 21 - 1.5.3.5 乘法运算符................................................................................................... - 21 - 1.5.3.6 加法运算符................................................................................................... - 21 - 1.5.3.7 按位移位运算符........................................................................................... - 21 - 1.5.3.8 关系运算符................................................................................................... - 22 - 1.5.3.9 等于运算符................................................................................................... - 22 - 阅几科技 - 4 - 1.5.3.10 按位逻辑运算符......................................................................................... - 22 - 1.5.3.11 逻辑运算符................................................................................................. - 22 - 1.5.3.12 条件运算符................................................................................................. - 23 - 1.5.3.13 赋值运算符................................................................................................. - 23 - 1.5.4 条件语句.................................................................................................................. - 23 - 1.5.4.1 if..else............................................................................................................. - 23 - 1.5.4.2 if..else if.......................................................................................................... - 24 - 1.5.4.3 switch ............................................................................................................. - 24 - 1.5.5 循环.......................................................................................................................... - 25 - 1.5.5.1 for................................................................................................................... - 25 - 1.5.5.2 for..in.............................................................................................................. - 25 - 1.5.5.3 for each..in...................................................................................................... - 26 - 1.5.5.4 while............................................................................................................... - 27 - 1.5.5.5 do..while......................................................................................................... - 27 - 1.5.6 函数.......................................................................................................................... - 28 - 1.5.6.1 函数的基本概念........................................................................................... - 28 - 1.5.6.2 函数参数....................................................................................................... - 32 - 1.5.6.3 函数作为对象............................................................................................... - 35 - 1.5.6.4 函数作用域................................................................................................... - 36 - 1.6 程序实例............................................................................................................................. - 37 - 1.6.1 创建一个受约束的布局.......................................................................................... - 37 - 1.6.2 使用列表类控件...................................................................................................... - 44 - 1.6.3 事件监听.................................................................................................................. - 48 - 1.6.4 Web服务 ................................................................................................................... - 51 - 阅几科技 - 5 - 1.1 Flex简介 Flex 是 Macromedia(现已被 Adobe 公司收购)发布的 presentation server (展现服务),它是 java web container 或者.netserver 的一个应用,根据.mxml 文件(纯粹的 xml 描述文件和 ActionScript3)产生相应得.swf 文件,传送到客户端, 由客户端的 flash player 或者 shockwave player 解释执行,给用户以丰富的客户体 验。 大名鼎鼎的 MacromediaFlash 是强大的矢量动画编辑工具,在做动画起家之后, Flash 一直在谋求 rich internet application(ria 富客户端)的霸主地位,最有影 响的是,已经推出了面向对象的编成脚本 ActionScript32.0,并且建立起类似于 java swing 的类库和相应 component(组件)。Flex 是通过 java 或者.net 等非 Flash 途径, 解释.mxml 文件组织 components,并生成相应得.swf 文件。Flex 的 component 和 flash 的 component 很相似,但是有所改进增强。 运用 Flash 是完全可以做到 flex 的效果的,为什么还需要 flex 呢?这里面有两个 原因: 1.1.1 为了迎合更多的developers(开发者)。 Flash 天生是为了 designer(设计者)设计的,界面还有 flash 的动画概念和程序 开发人员格格不入,为了吸引更多的 jsp/asp/php 等程序员,Macromedia 推出了 Flex 用非常简单的.mxml 来描述界面给 jsp/asp/php 程序人员使用.(x/d)html 非常相似, 而且 mxml 更加规范化、标准化。 1.1.2 为了一个标准。 大家一定听说过微软下一代系统 longhorn,在 longhorn 推出的同时微软也会推出 新的语言 xaml,一种界面描述语言,与之相应的就是 smart client 和 flex 非常相似 的东西。Mxml 和 Xaml 的也很相似,这是人机交互技术的进步的重要体现,即内部逻辑与 外部界面交互相分离。 1.2 ActionScript3 的特点 1.2.1 文本编辑 你可以在专家模式的 Actions 面板中直接输入脚本。当然,你也可以在弹出菜单 或工具箱列表中选择元素。 阅几科技 - 6 - 1.2.2 ActionScript3 与JavaScript之间的差异 ActionScript3 与 JavaScript 核心编程语言很相似,同样具有函数、变量、语句、 操作符、条件和循环等基本的编程概念。不了解 JavaScript 也可以学习和使用 ActionScript3。但是,如果了解 JavaScript,你就会对 ActionScript3 感到熟悉。 ActionScript3 与 JavaScript 之间主要有以下几点不同: ActionScript3 不支持浏览器特有的对象,如文档、窗口和锚点。 ActionScript3 不完全支持所有 JavaScript 的预定义对象。 ActionScript3 支持 JavaScript 中不 允许使用的语法结构(如 tellTarget 和 ifFrameLoaded 动作和 slash 语法)。 ActionScript3 不支持某些 JavaScript 语法结构(switch、continue、try、 catch、throw 和 labels 语句)。ActionScript3 不支持 JavaScript 的函数结构体。 在 ActionScript3 中,eval 动作仅执行变量的引用。在 JavaScript 中,未定义的 toString 的值是 undefined ,而在 ActionScript3 中,未定义的 toString 的值 是”“。 在 JavaScript,计算未定义数值型变量或表达式,得到的结果是 NaN。而在 ActionScript3 中,计算结果是 0。ActionScript3 不支持 Unicode 编码,它支持 ISO-8859-1 和 Shift-JIS 字符集。 1.2.3 数据类型 ActionScript3 支持以下数据类型:字符串、数值、逻辑、对象和电影剪辑。多种数 据类型的支持使你能够在 ActionScript3 中使用不同类型的信息。例如,你可以创建数 组和关联数组。 1.2.4 点语法 可以使用点语法获取和设置一个对象的属性和方法,包括电影剪辑实例和变量(例如, myMovieClip.childMovieClip.myVariable)。你也可以用点语法取代 Flash 4 中 使用的斜杠语法(myMovieClip/childMovieClip:myVariable)。 1.2.5 用户定义函数 用户可以根据需要,定义带参函数,让它返回一个值。这样,我们就可以在脚本中重用 代码块。在 ActionScript3 中,你可以通过 Call 动作重用代码,但不能传递参数,也 不能返回值。 1.2.6 本地变量 在 ActionScript3 中可以声明在动作列表或函数调用结束时过期的本地变量。这样, 你就可以管理内存和重用变量名。变量都是永久性的,即使是临时变量(如计数器)也保存 在动画中,直至动画结束。 阅几科技 - 7 - 1.2.7 预定义对象 可以使用 ActionScript3 预定义对象来访问和管理某些类型的信息。下面列出一些 预定义对象:ath(数学)对象:它的重要作用是对内建数学常数和函数的全面补充,例如 E(Euler 常数)、cos(余弦)和 atan(反正切)。 Date(日期)对象:使用 Date 对 象可以获取运行 Flash 播放器的系统的日期和时间信息。 Sound(声音)对象:使用 Sound 对象可以在动画中添加声音,能够在播放动画时控制声音。 例如,可以调整音量(setVolume)或平衡(setPan)。 Mouse(鼠标)对象:使用 Mouse 对象可以隐藏标准光标,让你能够使用自定义光标。MovieClip(电影剪辑)对象: 使用 MovieClip 对象,可以控制电影剪辑而无需使用打包动作(如 tellTarget)。可以 使用点语法(如 myMovieClip.play())调用电影剪辑实例的方法(如 play、loadMovie 或 duplicateMovieClip)。 1.2.8 剪辑动作 可以使用 onClipEvent 动作直接给编辑区中的电影剪辑实例分配动作。 onClipEvent 动作有 load、enterFrame、mouseMove 和 data 等事件,利用它可以创 建新的高级交互性。 1.2.9 调试器 使用调试器可以查看和修改在测试动画模式、Flash 独立播放器或浏览器中播放的动 画的变量和属性值。这样,你就可以很容易发现动作脚本中的问题。 1.2.10 提供上下文敏感帮助 在编写脚本的过程中,可以获得与正在使用的动作有关的信息。 1.2.11 XML支持 使用预定义的 XML 对象可以把 ActionScript3 转换为 XML 文档,然后传递到服务器 端应用中。也可以用 XML 对象把 XML 文档载入 Flash 动画中并加以解释。使用预定义的 XML Socket 对象可以创建不间断的服务器连接,为实时应用传递 XML 数据。 1.3 MXML介绍 MXML 是一个可以让你在 Adobe Flex 中布局用户界面组件的一种 XML 语言。 你也可以使用 MXML 声明来定义程序中的非可视化组件,比如对服务器端数据源的访问 以及用户界面组件和数据源之间的数据绑定。 MXML 标签与 ActionScript 类或者类中的属性是相对应的。当你编译你的 Flex 应 阅几科技 用程序的时候,Flex 解析你的 MXML 标签并且生成相应的 ActionScript 类。然后这些 ActionScript 类会被编译成 SWF 字节码存储到一个 SWF 文件中。 标签中的 mx 前缀是一个命名空间。它是通过在 Application 标签中 使用一个独一无二的 URL 来声明的。mx 前缀把在 mx 命名空间中的每个组件映射到它的完 全限定类名。这就是为什么 Flex 编译器可以在找到与 mx 命名空间中的 MXML 标签相对应 的 ActionScript 类。MXML 区分大小写,且文件名和变量标示名都区分大小写。 每个 MXML 文件必须以小写的”mxml”作为后缀,文件名要遵循 ActionScript 中变 量的命名规则。 在 ActionScript 中,变量名必须以字母或下划线开始,且只能包含字母、数字、和 下划线。 MXML 文件不能命名为”application”,”application”是主程序文件所采用的默 认标记,不可以再被使用,也不能和程序中任一组件的 id 值同名。不可以用 mx 做为目录 名,”mx”是 Flex Framework 的官方组件库的命名空间,受到 flex 编译码的保护。 通常情况下,flex 程序以下三个文件组成: 以 mxml 为后缀的程序文件 以 as 为后缀的 ActionScript 文件 以 css 为后缀的样式表文件 1.4 Flex Builder 3 接下来我们要重点介绍 Flex Builder 3,因为要用其进行开发。 安装 FlexBuilder3,过程略。 可以看出 FlexBuilder3 跟 eclipse 基本上是一样的,如果用过 SWT Designer 就会发现两者非常非常类似。 跟别的教程一样,HelloWorld 开始: - 8 - 阅几科技 1.4.1 先new一个FlexProject项目 - 9 - 阅几科技 1.4.2 工程命名 这儿说明一点 Application Type 使用默认的 Web Application,另一种 Desktop Application,是运行在 Adobe 公司 AIR 产品的桌面应用,大家可以在网络上了解一下, 这儿所讲的 FLEX 就是 Web 应用。 1.4.3 完成New Project后,出现如下界面 - 10 - 阅几科技 1.4.4 点击Design,出现如下界面 1.4.5 然后直接选择如下界面的label放到背景板上 或者是直接在 MXML 上写代码 - 11 - 阅几科技 - 12 - 一般 Flex 默认的字体大小为 10,这样的字体大小显得有些小,通常使用 12 以上的字 体大小,在这里就直接使用字体大小为 12。显示效果如下: 接下来就是保存文件,在保存的同时 FlexBuilder3 将 MXML 语言首先编译成 ActionScript 语言,然后再将 ActionScript 语言编译成 SWF 文件。 阅几科技 1.4.6 运行 1.5 编程基础 1.5.1 数据类型 在 ActionScript 中,可以将很多数据类型用作所创建的变量的数据类型。其中的 某些数据类型可以看作是"简单"或"基本"数据类型: • String:一个文本值,例如,一个名称或书中某一章的文字 • Numeric:对于 numeric 型数据,ActionScript3 包含三种特定的数据类型: o Number:任何数值,包括有小数部分或没有小数部分的值 o Int:一个整数(不带小数部分的整数) - 13 - o Uint:一个"无符号"整数,即不能为负数的整数 阅几科技 - 14 - • Boolean:一个 true 或 false 值,例如开关是否开启或两个值是否相等 简单数据类型表示单条信息:例如,单个数字或单个文本序列。然而,ActionScript 中定义的大部分数据类型都可以被描述为复杂数据类型,因为它们表示组合在一起的一组 值。例如,数据类型为 Date 的变量表示单个值 ─ 时间中的某个片刻。然而,该日期值 实际上表示为几个值:年、月、日、时、分、秒等等,它们都是单独的数字。所以,虽然我 们认为日期是单个值(可以通过创建一个 Date 变量将日期作为单个值来对待),而在计算 机内部却认为日期是组合在一起、共同定义单个日期的一组值。 大部分内置数据类型以及程序员定义的数据类型都是复杂数据类型。你可能认识下面的 一些复杂数据类型: • MovieClip:影片剪辑元件 • TextField:动态文本字段或输入文本字段 • SimpleButton:按钮元件 • Date:有关时间中的某个片刻的信息(日期和时间) 1.5.2 关于语法 1.5.2.1 区分大小写 ActionScript3 是一种区分大小写的语言。只是大小写不同的标识符会被视为不同。 例如,下面的代码创建两个不同的变量: var num1:int; var Num1:int; 1.5.2.2 点语法 可以通过点运算符 (.) 来访问对象的属性和方法。使用点语法,可以使用后跟点运算 符和属性名或方法名的实例名来引用类的属性或方法。以下面的类定义为例: class DotExample{ public var prop1:String; public function method1():void {} } 借助于点语法,可以使用在如下代码中创建的实例名来访问 prop1 属性和 method1() 方法: var myDotEx:DotExample = new DotExample(); myDotEx.prop1 = "hello"; myDotEx.method1(); 定义包时,可以使用点语法。可以使用点运算符来引用嵌套包。例如, EventDispatcher 类位于一个名为 events 的包中,该包嵌套在名为 flash 的包中。 可以使用下面的表达式来引用 events 包:flash.events 还可以使用此表达式来引用 EventDispatcher 类: flash.events.EventDispatcher 阅几科技 - 15 - 1.5.2.3 斜杠语法 ActionScript3 不支持斜杠语法。在早期的 ActionScript 版本中,斜杠语法用 于指示影片剪辑或变量的路径。 字面值 "字面值"是直接出现在代码中的值。下面的示例都是字面值: 17 "hello" -3 9.4 null undefined true false 字面值还可以组合起来构成复合字面值。数组文本括在中括号字符 ([]) 中,各数组 元素之间用逗号隔开。 数组文本可用于初始化数组。下面的几个示例显示了两个使用数组文本初始化的数组。 你可以使用 new 语句将复合字面值作为参数传递给 Array 类构造函数,但是,你还可以 在实例化下面的 ActionScript 核心类的实例时直接赋予字面值:Object、Array、 String、Number、int、uint、XML、XMLList 和 Boolean。 // 使用 new 语句。 var myStrings:Array = new Array(["alpha", "beta", "gamma"]); var myNums:Array = new Array([1,2,3,5,8]); // 直接赋予字面值。 var myStrings:Array = ["alpha", "beta", "gamma"]; var myNums:Array = [1,2,3,5,8]; 字面值还可用来初始化通用对象。通用对象是 Object 类的一个实例。对象字面值括 在大括号 ({}) 中,各对象属性之间用逗号隔开。每个属性都用冒号字符 (:) 进行声明, 冒号用于分隔属性名和属性值。 可以使用 new 语句创建一个通用对象并将该对象的字面值作为参数传递给 Object 类构造函数,也可以在声明实例时直接将对象字面值赋给实例。下面的示例创建一个新的通 用对象,并使用三个值分别设置为 1、2 和 3 的属性(propA、propB 和 propC)初始 化该对象: // 使用 new 语句。 var myObject:Object = new Object({propA:1, propB:2, propC:3}); // 直接赋予字面值。 var myObject:Object = {propA:1, propB:2, propC:3}; 1.5.2.4 分号 可以使用分号字符 (;) 来终止语句。如果你省略分号字符,则编译器将假设每一行代 码代表一条语句。由于很多程序员都习惯使用分号来表示语句结束,因此,如果你坚持使用 阅几科技 - 16 - 分号来终止语句,则代码会更易于阅读。 使用分号终止语句可以在一行中放置多个语句,但是这样会使代码变得难以阅读。 1.5.2.5 小括号 在 ActionScript3 中,可以通过三种方式来使用小括号 (())。首先,可以使用小 括号来更改表达式中的运算顺序。组合到小括号中的运算总是最先执行。例如,小括号可用 来改变如下代码中的运算顺序: trace(2 + 3 * 4); // 14 trace( (2 + 3) * 4); // 20 第二,可以结合使用小括号和逗号运算符 (,) 来计算一系列表达式并返回最后一个表 达式的结果,如下面的示例所示: var a:int = 2; var b:int = 3; trace((a++, b++, a+b)); // 7 第三,可以使用小括号来向函数或方法传递一个或多个参数,如下面的示例所示,此示 例向 trace() 函数传递一个字符串值: trace("hello"); // hello 1.5.2.6 注释 ActionScript3 代码支持两种类型的注释:单行注释和多行注释。这些注释机制与 C++ 和 Java 中的注释机制类似。编译器将忽略标记为注释的文本。 单行注释以两个正斜杠字符 (//) 开头并持续到该行的末尾。例如,下面的代码包含 一个单行注释: var someNumber:Number = 3; // 单行注释 多行注释以一个正斜杠和一个星号 (/*) 开头,以一个星号和一个正斜杠 (*/) 结 尾。 /* 这是一个可以跨 多行代码的多行注释。 */ 1.5.2.7 关键字和保留字 "保留字"是一些单词,因为这些单词是保留给 ActionScript 使用的,所以,不能 在代码中将它们用作标识符。保留字包括"词汇关键字",编译器将词汇关键字从程序的命 名空间中删除。如果你将词汇关键字用作标识符,则编译器会报告一个错误。下表列出了 ActionScript3 词汇关键字: as break case catch class const continue default delete do else extends false finally for function if implements import in instanceof interface internal is 阅几科技 - 17 - native new null package private protected public return super switch this throw to true try typeof use var void while with 有一小组名为"句法关键字"的关键字,这些关键字可用作标识符,但是在某些上下文 中具有特殊的含义。下表列出了 ActionScript3 句法关键字: each get set namespace include dynamic final native override static 还有几个有时称为" 供将来使用的保留字" 的标识符。这些标识符不是为 ActionScript3 保留的,但是其中的一些可能会被采用 ActionScript3 的软件视为 关键字。你可以在自己的代码中使用其中的许多标识符,但是 Adobe 不建议你使用它们, 因为它们可能会在以后的 ActionScript 版本中作为关键字出现。 abstract boolean byte cast char debugger double enum export float goto intrinsic long prototype short synchronized throws to transient type virtual volatile 1.5.2.8 常量 ActionScript3 支持 const 语句,该语句可用来创建常量。常量是指具有无法改 变的固定值的属性。只能为常量赋值一次,而且必须在最接近常量声明的位置赋值。例如, 如果将常量声明为类的成员,则只能在声明过程中或者在类构造函数中为常量赋值。 下面的代码声明两个常量。第一个常量 MINIMUM 是在声明语句中赋值的,第二个常 量 MAXIMUM 是在构造函数中赋值的。 class A{ public const MINIMUM:int = 0; public const MAXIMUM:int; public function A(){ MAXIMUM = 10; } } var a:A = new A(); trace(a.MINIMUM); // 0 trace(a.MAXIMUM); // 10 如果你尝试以其它任何方法向常量赋予初始值,则会出现错误。例如,如果你尝试在类 的外部设置 MAXIMUM 的初始值,将会出现运行时错误。 class A{ 阅几科技 - 18 - public const MINIMUM:int = 0; public const MAXIMUM:int; } var a:A = new A(); a["MAXIMUM"] = 10; // 运行时错误 Flash Player API 定义了一组广泛的常量供你使用。按照惯例,ActionScript 中 的常量全部使用大写字母,各个单词之间用下划线字符 (_) 分隔。例如,MouseEvent 类 定义将此命名惯例用于其常量,其中每个常量都表示一个与鼠标输入有关的事件: package flash.events{ public class MouseEvent extends Event{ public static const CLICK:String = "click"; public static const DOUBLE_CLICK:String = "doubleClick"; public static const MOUSE_DOWN:String = "mouseDown"; public static const MOUSE_MOVE:String = "mouseMove"; ... } 1.5.3 运算符 运算符是一种特殊的函数,它们具有一个或多个操作数并返回相应的值。"操作数"是 被运算符用作输入的值,通常是字面值、变量或表达式。例如,在下面的代码中,将加法运 算符 (+) 和乘法运算符 (*) 与三个字面值操作数(2、3 和 4)结合使用来返回一个值。 赋值运算符 (=) 随后使用该值将所返回的值 14 赋给变量 sumNumber。 var sumNumber:uint = 2 + 3 * 4; // uint = 14 运算符可以是一元、二元或三元的。"一元"运算符有 1 个操作数。例如,递增运算符 (++) 就是一元运算符,因为它只有一个操作数。"二元"运算符有 2 个操作数。例如,除 法运算符 (/) 有 2 个操作数。"三元"运算符有 3 个操作数。例如,条件运算符 (?:) 具 有 3 个操作数。 有些运算符是"重载的",这意味着它们的行为因传递给它们的操作数的类型或数量而 异。例如,加法运算符 (+) 就是一个重载运算符,其行为因操作数的数据类型而异。如果 两个操作数都是数字,则加法运算符会返回这些值的和。如果两个操作数都是字符串,则加 法运算符会返回这两个操作数连接后的结果。下面的示例代码说明运算符的行为如何因操作 数而异: trace(5 + 5); // 10 trace("5" + "5"); // 55 运算符的行为还可能因所提供的操作数的数量而异。减法运算符 (-) 既是一元运算符 又是二元运算符。对于减法运算符,如果只提供一个操作数,则该运算符会对操作数求反并 返回结果;如果提供两个操作数,则减法运算符返回这两个操作数的差。下面的示例说明首 先将减法运算符用作一元运算符,然后再将其用作二元运算符。 trace(-3); // -3 trace(7-2); // 5 阅几科技 - 19 - 1.5.3.1 运算符的优先级和结合律 运算符的优先级和结合律决定了运算符的处理顺序。虽然对于熟悉算术的人来说,编译 器先处理乘法运算符 (*) 然后再处理加法运算符 (+) 似乎是自然而然的事情,但实际上 编译器要求显式指定先处理哪些运算符。此类指令统称为"运算符优先级"。ActionScript 定义了一个默认的运算符优先级,你可以使用小括号运算符 (()) 来改变它。例如,下面 的代码改变上一个示例中的默认优先级,以强制编译器先处理加法运算符,然后再处理乘法 运算符: var sumNumber:uint = (2 + 3) * 4; // uint == 20 你可能会遇到这样的情况:同一个表达式中出现两个或更多个具有相同的优先级的运算 符。在这些情况下,编译器使用"结合律"的规则来确定先处理哪个运算符。除了赋值运算 符之外,所有二进制运算符都是"左结合"的,也就是说,先处理左边的运算符,然后再处 理右边的运算符。赋值运算符和条件运算符 (?:) 都是"右结合"的,也就是说,先处理右 边的运算符,然后再处理左边的运算符。 例如,考虑小于运算符 (<) 和大于运算符 (>),它们具有相同的优先级。如果将这 两个运算符用于同一个表达式中,那么,由于这两个运算符都是左结合的,因此先处理左边 的运算符。也就是说,以下两个语句将生成相同的输出结果: trace(3 > 2 < 1); // false trace((3 > 2) < 1); // false 将首先处理大于运算符,这会生成值 true,因为操作数 3 大于操作数 2。随后,将 值 true 与操作数 1 一起传递给小于运算符。下面的代码表示此中间状态: trace((true) < 1); 小于运算符将值 true 转换为数值 1,然后将该数值与第二个操作数 1 进行比较, 这将返回值 false(因为值 1 不小于 1)。 trace(1 < 1); // false 你可以用括号运算符来改变默认的左结合律。你可以通过用小括号括起小于运算符及其 操作数来命令编译器先处理小于运算符。下面的示例使用与上一个示例相同的数,但是因为 使用了小括号运算符,所以生成不同的输出结果: trace(3 > (2 < 1)); // true 将首先处理小于运算符,这会生成值 false,因为操作数 2 不小于操作数 1。值 false 随后将与操作数 3 一起传递给大于运算符。下面的代码表示此中间状态: trace(3 > (false)); 大于运算符将值 false 转换为数值 0,然后将该数值与另一个操作数 3 进行比较, 这将返回 true(因为 3 大于 0)。 trace(3 > 0); // true 下表按优先级递减的顺序列出了 ActionScript3 中的运算符。该表内同一行中的运 算符具有相同的优先级。在该表中,每行运算符都比位于其下方的运算符的优先级高。 组 运算符 主要 [] {x:y} () f(x) new x.y x[y] <> @ :: .. 后缀 x++ x-- 一元 ++x --x + - ~ ! delete typeof void 乘法 * / % 加法 + - 按位移位 << >> >>> 阅几科技 - 20 - 关系 < > <= >= as in instanceof is 等于 == != === !== 按位"与" & 按位"异或" ^ 按位"或" | 逻辑"与" && 逻辑"或" || 条件 ?: 赋值 = *= /= %= += -= <<= >>= >>>= &= ^= |= 逗号 , 1.5.3.2 主要运算符 主要运算符包括那些用来创建 Array 和 Object 字面值、对表达式进行分组、调用 函数、实例化类实例以及访问属性的运算符。 下表列出了所有主要运算符,它们具有相同的优先级。属于 E4X 规范的运算符用 (E4X) 来表示。 运算符 执行的运算 [] 初始化数组 {x:y} 初始化对象 () 对表达式进行分组 f(x) 调用函数 new 调用构造函数 x.y x[y] 访问属性 <> 初始化 XMLList 对象 (E4X) @ 访问属性 (E4X) :: 限定名称 (E4X) .. 访问子级 XML 元素 (E4X) 1.5.3.3 后缀运算符 后缀运算符只有一个操作数,它递增或递减该操作数的值。虽然这些运算符是一元运算 符,但是它们有别于其它一元运算符,被单独划归到了一个类别,因为它们具有更高的优先 级和特殊的行为。在将后缀运算符用作较长表达式的一部分时,会在处理后缀运算符之前返 回表达式的值。例如,下面的代码说明如何在递增值之前返回表达式 xNum++ 的值: var xNum:Number = 0; trace(xNum++); // 0 trace(xNum); // 1 下表列出了所有的后缀运算符,它们具有相同的优先级: 运算符 执行的运算 ++ 递增(后缀) -- 递减(后缀) 阅几科技 - 21 - 1.5.3.4 一元运算符 一元运算符只有一个操作数。这一组中的递增运算符 (++) 和递减运算符 (--) 是" 前缀运算符",这意味着它们在表达式中出现在操作数的前面。前缀运算符与它们对应的后 缀运算符不同,因为递增或递减操作是在返回整个表达式的值之前完成的。例如,下面的代 码说明如何在递增值之后返回表达式 ++xNum 的值: var xNum:Number = 0; trace(++xNum); // 1 trace(xNum); // 1 下表列出了所有的一元运算符,它们具有相同的优先级: 运算符 执行的运算 ++ 递增(前缀) -- 递减(前缀) + 一元 + - 一元 -(非) ! 逻辑"非" ~ 按位"非" delete 删除属性 typeof 返回类型信息 void 返回 undefined 值 1.5.3.5 乘法运算符 乘法运算符具有两个操作数,它执行乘、除或求模计算。 下表列出了所有的乘法运算符,它们具有相同的优先级: 运算符 执行的运算 * 乘法 / 除法 % 求模 1.5.3.6 加法运算符 加法运算符有两个操作数,它执行加法或减法计算。下表列出了所有加法运算符,它们 具有相同的优先级: 运算符 执行的运算 + 加法 - 减法 1.5.3.7 按位移位运算符 按位移位运算符有两个操作数,它将第一个操作数的各位按第二个操作数指定的长度移 位。下表列出了所有按位移位运算符,它们具有相同的优先级: 阅几科技 - 22 - 运算符 执行的运算 << 按位向左移位 >> 按位向右移位 >>> 按位无符号向右移位 1.5.3.8 关系运算符 关系运算符有两个操作数,它比较两个操作数的值,然后返回一个布尔值。下表列出了 所有关系运算符,它们具有相同的优先级: 运算符 执行的运算 < 小于 > 大于 <= 小于或等于 >= 大于或等于 as 检查数据类型 in 检查对象属性 instanceof 检查原型链 is 检查数据类型 1.5.3.9 等于运算符 等于运算符有两个操作数,它比较两个操作数的值,然后返回一个布尔值。下表列出了 所有等于运算符,它们具有相同的优先级: 运算符 执行的运算 == 等于 != 不等于 === 严格等于 !== 严格不等于 1.5.3.10 按位逻辑运算符 按位逻辑运算符有两个操作数,它执行位级别的逻辑运算。按位逻辑运算符具有不同的 优先级;下表按优先级递减的顺序列出了按位逻辑运算符: 运算符 执行的运算 & 按位"与" ^ 按位"异或" | 按位"或" 1.5.3.11 逻辑运算符 逻辑运算符有两个操作数,它返回布尔结果。逻辑运算符具有不同的优先级;下表按优 先级递减的顺序列出了逻辑运算符: 阅几科技 - 23 - 运算符 执行的运算 && 逻辑"与" || 逻辑"或" 1.5.3.12 条件运算符 条件运算符是一个三元运算符,也就是说它有三个操作数。条件运算符是应用 if..else 条件语句的一种简便方法。 运算符 执行的运算 ?: 条件 1.5.3.13 赋值运算符 赋值运算符有两个操作数,它根据一个操作数的值对另一个操作数进行赋值。下表列出 了所有赋值运算符,它们具有相同的优先级: 运算符 执行的运算 = 赋值 *= 乘法赋值 /= 除法赋值 %= 求模赋值 += 加法赋值 -= 减法赋值 <<= 按位向左移位赋值 >>= 按位向右移位赋值 >>>= 按位无符号向右移位赋值 &= 按位"与"赋值 ^= 按位"异或"赋值 |= 按位"或"赋值 1.5.4 条件语句 1.5.4.1 if..else if..else 条件语句用于测试一个条件,如果该条件存在,则执行一个代码块,否则 执行替代代码块。例如,下面的代码测试 x 的值是否超过 20,如果是,则生成一个 trace() 函数,否则生成另一个 trace() 函数: if (x > 20){ trace("x is > 20"); } else{ trace("x is <= 20"); 阅几科技 - 24 - } 如果你不想执行替代代码块,可以仅使用 if 语句,而不用 else 语句。 1.5.4.2 if..else if 可以使用 if..else if 条件语句来测试多个条件。例如,下面的代码不仅测试 x 的 值是否超过 20,而且还测试 x 的值是否为负数: if (x > 20){ trace("x is > 20"); } else if (x < 0){ trace("x is negative"); } 如果 if 或 else 语句后面只有一条语句,则无需用大括号括起后面的语句。例如, 下面的代码不使用大括号: if (x > 0) trace("x is positive"); else if (x < 0) trace("x is negative"); else trace("x is 0"); 但是,Adobe 建议你始终使用大括号,因为以后在缺少大括号的条件语句中添加语句 时,可能会出现意外的行为。例如,在下面的代码中,无论条件的计算结果是否为 true, positiveNums 的值总是按 1 递增: var x:int; var positiveNums:int = 0; if (x > 0) trace("x is positive"); positiveNums++; trace(positiveNums); // 1 1.5.4.3 switch 如果多个执行路径依赖于同一个条件表达式,则 switch 语句非常有用。它的功能大 致相当于一系列 if..else if 语句,但是它更便于阅读。switch 语句不是对条件进行 测试以获得布尔值,而是对表达式进行求值并使用计算结果来确定要执行的代码块。代码块 以 case 语句开头,以 break 语句结尾。例如,下面的 switch 语句基于由 Date.getDay() 方法返回的日期值输出星期日期: var someDate:Date = new Date(); var dayNum:uint = someDate.getDay(); switch(dayNum){ case 0: trace("Sunday"); break; 阅几科技 - 25 - case 1: trace("Monday"); break; case 2: trace("Tuesday"); break; case 3: trace("Wednesday"); break; case 4: trace("Thursday"); break; case 5: trace("Friday"); break; case 6: trace("Saturday"); break; default: trace("Out of range"); break; } 1.5.5 循环 1.5.5.1 for for 循环用于循环访问某个变量以获得特定范围的值。必须在 for 语句中提供 3 个 表达式:一个设置了初始值的变量,一个用于确定循环何时结束的条件语句,以及一个在每 次循环中都更改变量值的表达式。例如,下面的代码循环 5 次。变量 i 的值从 0 开始到 4 结束,输出结果是从 0 到 4 的 5 个数字,每个数字各占 1 行。 var i:int; for (i = 0; i < 5; i++){ trace(i); } 1.5.5.2 for..in for..in 循环用于循环访问对象属性或数组元素。例如,可以使用 for..in 循环来 循环访问通用对象的属性(不按任何特定的顺序来保存对象的属性,因此属性可能以看似随 机的顺序出现): var myObj:Object = {x:20, y:30}; for (var i:String in myObj){ trace(i + ": " + myObj[i]); 阅几科技 - 26 - } // 输出: // x: 20 // y: 30 还可以循环访问数组中的元素: var myArray:Array = ["one", "two", "three"]; for (var i:String in myArray){ trace(myArray[i]); } // 输出: // one // two // three 如果对象是自定义类的一个实例,则除非该类是动态类,否则将无法循环访问该对象的 属性。即便对于动态类的实例,也只能循环访问动态添加的属性。 1.5.5.3 for each..in for each..in 循环用于循环访问集合中的项目,它可以是 XML 或 XMLList 对象 中的标签、对象属性保存的值或数组元素。例如,如下面所摘录的代码所示,你可以使用 for each..in 循环来循环访问通用对象的属性,但是与 for..in 循环不同的是,for each..in 循环中的迭代变量包含属性所保存的值,而不包含属性的名称: var myObj:Object = {x:20, y:30}; for each (var num in myObj){ trace(num); } // 输出: // 20 // 30 你可以循环访问 XML 或 XMLList 对象,如下面的示例所示: var myXML:XML = Jane Susan John ; for each (var item in myXML.fname){ trace(item); } /* 输出 Jane Susan John */ 还可以循环访问数组中的元素,如下面的示例所示: 阅几科技 - 27 - var myArray:Array = ["one", "two", "three"]; for each (var item in myArray){ trace(item); } // 输出: // one // two // three 如果对象是密封类的实例,则你将无法循环访问该对象的属性。即使对于动态类的实例, 也无法循环访问任何固定属性(即,作为类定义的一部分定义的属性)。 1.5.5.4 while while 循环与 if 语句相似,只要条件为 true,就会反复执行。例如,下面的代码 与 for 循环示例生成的输出结果相同: var i:int = 0; while (i < 5){ trace(i); i++; } 使用 while 循环(而非 for 循环)的一个缺点是,编写的 while 循环中更容易出 现无限循环。如果省略了用来递增计数器变量的表达式,则 for 循环示例代码将无法编译, 而 while 循环示例代码仍然能够编译。若没有用来递增 i 的表达式,循环将成为无限循 环。 1.5.5.5 do..while do..while 循环是一种 while 循环,它保证至少执行一次代码块,这是因为在执行 代码块后才会检查条件。下面的代码显示了 do...while 循环的一个简单示例,即使条件 不满足,该示例也会生成输出结果: var i:int = 5; do{ trace(i); i++; } while (i < 5); // 输出:5 阅几科技 - 28 - 1.5.6 函数 1.5.6.1 函数的基本概念 1.5.6.1.1 调用函数 可通过使用后跟小括号运算符 (()) 的函数标识符来调用函数。要发送给函数的任何 函数参数都括在小括号中。例如,贯穿于本书始末的 trace() 函数,它是 Flash Player API 中的顶级函数: trace("Use trace to help debug your script"); 如果要调用没有参数的函数,则必须使用一对空的小括号。例如,可以使用没有参数的 Math.random() 方法来生成一个随机数: var randomNum:Number = Math.random(); 1.5.6.1.2 定义你自己的函数 在 ActionScript3 中可通过两种方法来定义函数:使用函数语句和使用函数表达 式。你可以根据自己的编程风格(偏于静态还是偏于动态)来选择相应的方法。如果你倾向 于采用静态或严格模式的编程,则应使用函数语句来定义函数。如果你有特定的需求,需要 用函数表达式来定义函数,则应这样做。函数表达式更多地用在动态编程或标准模式编程中。 1.5.6.1.3 函数语句 函数语句是在严格模式下定义函数的首选方法。函数语句以 function 关键字开头, 后跟: 函数名 用小括号括起来的逗号分隔参数列表 用大括号括起来的函数体 ─ 即,在调用函数时要执行的 ActionScript 代码 例如,下面的代码创建一个定义一个参数的函数,然后将字符串"hello"用作参数值 来调用该函数: function traceParameter(aParam:String){ trace(aParam); } traceParameter("hello"); // hello 1.5.6.1.4 函数表达式 声明函数的第二种方法就是结合使用赋值语句和函数表达式,函数表达式有时也称为函 数字面值或匿名函数。这是一种较为繁杂的方法,在早期的 ActionScript 版本中广为 使用。 阅几科技 - 29 - 带有函数表达式的赋值语句以 var 关键字开头,后跟: 函数名 冒号运算符 (:) 指示数据类型的 Function 类 赋值运算符 (=) function 关键字 用小括号括起来的逗号分隔参数列表 用大括号括起来的函数体 ─ 即,在调用函数时要执行的 ActionScript 代码 例如,下面的代码使用函数表达式来声明 traceParameter 函数: var traceParameter:Function = function (aParam:String){ trace(aParam); }; traceParameter("hello"); // hello 请注意,就像在函数语句中一样,在上面的代码中也没有指定函数名。函数表达式和函 数语句的另一个重要区别是,函数表达式是表达式,而不是语句。这意味着函数表达式不能 独立存在,而函数语句则可以。函数表达式只能用作语句(通常是赋值语句)的一部分。下 面的示例显示了一个赋予数组元素的函数表达式: var traceArray:Array = new Array(); traceArray[0] = function (aParam:String){ trace(aParam); }; traceArray[0]("hello"); 1.5.6.1.5 在函数语句和函数表达式之间进行选择 原则上,除非在特殊情况下要求使用表达式,否则应使用函数语句。函数语句较为简洁, 而且与函数表达式相比,更有助于保持严格模式和标准模式的一致性。 函数语句比包含函数表达式的赋值语句更便于阅读。与函数表达式相比,函数语句使代 码更为简洁而且不容易引起混淆,因为函数表达式既需要 var 关键字又需要 function 关键字。 函数语句更有助于保持严格模式和标准模式的一致性,因为在这两种编译器模式下,均 可以借助点语法来调用使用函数语句声明的方法。但这对于用函数表达式声明的方法却不一 定成立。例如,下面的代码定义了一个具有两个方法的 Example 类: methodExpression()(用函数表达式声明)和 methodStatement()(用函数语句声 明)。在严格模式下,不能使用点语法来调用 methodExpression() 方法。 class Example{ var methodExpression = function() {} function methodStatement() {} } var myEx:Example = new Example(); myEx.methodExpression(); // 在严格模式下出错,但在标准模式下正常 myEx.methodStatement(); // 在严格模式和标准模式下均正常 一般认为,函数表达式更适合于关注运行时行为或动态行为的编程。如果你喜欢使用严 格模式,但是还需要调用使用函数表达式声明的方法,则可以使用这两种方法中的任一方法。 阅几科技 - 30 - 首先,可以使用中括号 ([]) 代替点运算符 (.) 来调用该方法。下面的方法调用在严格 模式和标准模式下都能够成功执行: myExample["methodLiteral"](); 第二,你可以将整个类声明为动态类。尽管这样你就可以使用点运算符来调用方法,但 缺点是,该类的所有实例在严格模式下都将丢失一些功能。例如,如果你尝试访问动态类实 例的未定义属性,则编译器不生成错误。 在某些情况下,函数表达式非常有用。函数表达式的一个常见用法就是用于那些使用一 次后便丢弃的函数。另一个用法就是向原型属性附加函数,这个用法不太常见。 函数语句与函数表达式之间有两个细微的区别,在选择要使用的方法时,应考虑这两个 区别。第一个区别体现在内存管理和垃圾回收方面,因为函数表达式不像对象那样独立存在。 换言之,当你将某个函数表达式分配给另一个对象(如数组元素或对象属性)时,就会在代 码中创建对该函数表达式的唯一引用。如果该函数表达式所附加到的数组或对象脱离作用域 或由于其它原因不再可用,你将无法再访问该函数表达式。如果删除该数组或对象,该函数 表达式所使用的内存将符合垃圾回收条件,这意味着内存符合回收条件并且可重新用于其它 用途。 下面的示例说明对于函数表达式,一旦删除该表达式所赋予的属性,该函数就不再可用。 Test 类是动态的,这意味着你可以添加一个名为 functionExp 的属性来保存函数表达 式。functionExp() 函数可以用点运算符来调用,但是一旦删除了 functionExp 属性, 就无法再访问该函数。 dynamic class Test {} var myTest:Test = new Test(); // 函数表达式 myTest.functionExp = function () { trace("Function expression") }; myTest.functionExp(); // 函数表达式 delete myTest.functionExp; myTest.functionExp(); // 出错 另一方面,如果该函数最初是用函数语句定义的,那么,该函数将以对象的形式独立存 在,即使在你删除它所附加到的属性之后,该函数仍将存在。delete 运算符仅适用于对 象的属性,因此,即使是用于删除 stateFunc() 函数本身的调用也不工作。 dynamic class Test {} var myTest:Test = new Test(); // 函数语句 function stateFunc() { trace("Function statement") } myTest.statement = stateFunc; myTest.statement(); // 函数语句 delete myTest.statement; delete stateFunc; // 不起作用 stateFunc(); // 函数语句 myTest.statement(); // 错误 函数语句与函数表达式之间的第二个区别是,函数语句存在于定义它们的整个作用域 (包括出现在该函数语句前面的语句)内。与之相反,函数表达式只是为后续的语句定义的。 例如,下面的代码能够在定义 scopeTest() 函数之前成功调用它: statementTest(); // statementTest 阅几科技 - 31 - function statementTest():void{ trace("statementTest"); } 函数表达式只有在定义之后才可用,因此,下面的代码会生成运行时错误: expressionTest(); // 运行时错误 var expressionTest:Function = function (){ trace("expressionTest"); } 1.5.6.1.6 从函数中返回值 要从函数中返回值,请使用后跟要返回的表达式或字面值的 return 语句。例如,下 面的代码返回一个表示参数的表达式: function doubleNum(baseNum:int):int{ return (baseNum * 2); } 请注意,return 语句会终止该函数,因此,不会执行位于 return 语句下面的任何 语句,如下所示: function doubleNum(baseNum:int):int { return (baseNum * 2); trace("after return"); // 不会执行这条 trace 语句。 } 在严格模式下,如果你选择指定返回类型,则必须返回相应类型的值。例如,下面的代 码在严格模式下会生成错误,因为它们不返回有效值: function doubleNum(baseNum:int):int{ trace("after return"); } 1.5.6.1.7 嵌套函数 你可以嵌套函数,这意味着函数可以在其它函数内部声明。除非将对嵌套函数的引用传 递给外部代码,否则嵌套函数将仅在其父函数内可用。例如,下面的代码在 getNameAndVersion() 函数内部声明两个嵌套函数: function getNameAndVersion():String{ function getVersion():String{ return "9"; } function getProductName():String{ return "Flash Player"; } return (getProductName() + " " + getVersion()); } trace(getNameAndVersion()); // Flash Player 9 阅几科技 - 32 - 在将嵌套函数传递给外部代码时,它们将作为函数闭包传递,这意味着嵌套函数保留在 定义该函数时处于作用域内的任何定义。 1.5.6.2 函数参数 1.5.6.2.1 按值或按引用传递参数 在许多编程语言中,一定要了解按值传递参数与按引用传递参数之间的区别,二者之间 的区别会影响代码的设计方式。 按值传递意味着将参数的值复制到局部变量中以便在函数内使用。按引用传递意味着将 只传递对参数的引用,而不传递实际值。这种方式的传递不会创建实际参数的任何副本,而 是会创建一个对变量的引用并将它作为参数传递,并且会将它赋给局部变量以便在函数内部 使用。局部变量是对函数外部的变量的引用,它使你能够更改初始变量的值。 在 ActionScript3 中,所有的参数均按引用传递,因为所有的值都存储为对象。但 是,属于基元数据类型(包括 Boolean、Number、int、uint 和 String)的对象具 有一些特殊运算符,这使它们可以像按值传递一样工作。例如,下面的代码创建一个名为 passPrimitives() 的函数,该函数定义了两个类型均为 int、名称分别为 xParam 和 yParam 的参数。这些参数与在 passPrimitives() 函数体内声明的局部变量类似。当 使用 xValue 和 yValue 参数调用函数时,xParam 和 yParam 参数将用对 int 对象 的引用进行初始化,int 对象由 xValue 和 yValue 表示。因为参数是基元值,所以它 们像按值传递一样工作。尽管 xParam 和 yParam 最初仅包含对 xValue 和 yValue 对象的引用,但是,对函数体内的变量的任何更改都会导致在内存中生成这些值的新副本。 function passPrimitives(xParam:int, yParam:int):void{ xParam++; yParam++; trace(xParam, yParam); } var xValue:int = 10; var yValue:int = 15; trace(xValue, yValue); // 10 15 passPrimitives(xValue, yValue); // 11 16 trace(xValue, yValue); // 10 15 在 passPrimitives() 函数内部,xParam 和 yParam 的值递增,但这不会影响 xValue 和 yValue 的值,如上一条 trace 语句所示。即使参数的命名与 xValue 和 yValue 变量的命名完全相同也是如此,因为函数内部的 xValue 和 yValue 将指向内 存中的新位置,这些位置不同于函数外部同名的变量所在的位置。 其它所有对象(即不属于基元数据类型的对象)始终按引用传递,这样你就可以更改初 始变量的值。例如,下面的代码创建一个名为 objVar 的对象,该对象具有两个属性:x 和 y。该对象作为参数传递给 passByRef() 函数。因为该对象不是基元类型,所以它不但 按引用传递,而且还保持一个引用。这意味着对函数内部的参数的更改将会影响到函数外部 的对象属性。 function passByRef(objParam:Object):void{ objParam.x++; 阅几科技 - 33 - objParam.y++; trace(objParam.x, objParam.y); } var objVar:Object = {x:10, y:15}; trace(objVar.x, objVar.y); // 10 15 passByRef(objVar); // 11 16 trace(objVar.x, objVar.y); // 11 16 objParam 参数与全局 objVar 变量引用相同的对象。正如在本示例的 trace 语句 中所看到的一样,对 objParam 对象的 x 和 y 属性所做的更改将反映在 objVar 对象 中。 1.5.6.2.2 默认参数值 ActionScript3 中新增了为函数声明"默认参数值"的功能。如果在调用具有默认参 数值的函数时省略了具有默认值的参数,那么,将使用在函数定义中为该参数指定的值。所 有具有默认值的参数都必须放在参数列表的末尾。指定为默认值的值必须是编译时常量。如 果某个参数存在默认值,则会有效地使该参数成为"可选参数"。没有默认值的参数被视为" 必需的参数"。 例如,下面的代码创建一个具有三个参数的函数,其中的两个参数具有默认值。当仅用 一个参数调用该函数时,将使用这些参数的默认值。 function defaultValues(x:int, y:int = 3, z:int = 5):void{ trace(x, y, z); } defaultValues(1); // 1 3 5 1.5.6.2.3 arguments 对象 在将参数传递给某个函数时,可以使用 arguments 对象来访问有关传递给该函数的 参数的信息。arguments 对象的一些重要方面包括: arguments 对象是一个数组,其中包括传递给函数的所有参数。 arguments.length 属性报告传递给函数的参数数量。 arguments.callee 属性提供对函数本身的引用,该引用可用于递归调用函数表达 式。 注意: 如果将任何参数命名为 arguments,或者使用 ...(rest) 参数,则 arguments 对象不可用。 在 ActionScript3 中,函数调用中所包括的参数的数量可以大于在函数定义中所指 定的参数数量,但是,如果参数的数量小于必需参数的数量,在严格模式下将生成编译器错 误。你可以使用 arguments 对象的数组样式来访问传递给函数的任何参数,而无需考虑 是否在函数定义中定义了该参数。下面的示例使用 arguments 数组及 arguments.length 属性来输出传递给 traceArgArray() 函数的所有参数: function traceArgArray(x:int):void{ for (var i:uint = 0; i < arguments.length; i++){ trace(arguments[i]); } 阅几科技 - 34 - } traceArgArray(1, 2, 3); // 输出: // 1 // 2 // 3 arguments.callee 属性通常用在匿名函数中以创建递归。你可以使用它来提高代 码的灵活性。如果递归函数的名称在开发周期内的不同阶段会发生改变,而且你使用的是 arguments.callee(而非函数名),则不必花费精力在函数体内更改递归调用。在下面 的函数表达式中,使用 arguments.callee 属性来启用递归: var factorial:Function = function (x:uint){ if(x == 0) { return 1; } else{ return (x * arguments.callee(x - 1)); } } trace(factorial(5)); // 120 如果你在函数声明中使用 ...(rest) 参数,则不能使用 arguments 对象,而必须 使用为参数声明的参数名来访问参数。 还应避免将 "arguments" 字符串作为参数名,因为它将遮蔽 arguments 对象。例 如,如果重写 traceArgArray() 函数,以便添加 arguments 参数,那么,函数体内 对 arguments 的引用所引用的将是该参数,而不是 arguments 对象。下面的代码不生 成输出结果: function traceArgArray(x:int, arguments:int):void{ for (var i:uint = 0; i < arguments.length; i++){ trace(arguments[i]); } } traceArgArray(1, 2, 3); // 无输出 在早期的 ActionScript 版本中,arguments 对象还包含一个名为 caller 的属 性,该属性是对当前函数的引用。ActionScript3 中没有 caller 属性,但是,如果你 需要引用调用函数,则可以更改调用函数,以使其传递一个额外的参数来引用它本身。 1.5.6.2.4 ...(rest) 参数 ActionScript3 中引入了一个称为 ...(rest) 参数的新参数声明。此参数可用来 指定一个数组参数以接受任意多个以逗号分隔的参数。此参数可以拥有保留字以外的任意名 阅几科技 - 35 - 称。此参数声明必须是最后一个指定的参数。使用此参数会使 arguments 对象变得不可 用。尽管 ...(rest) 参数提供了与 arguments 数组和 arguments.length 属性相 同的功能,但是它不提供与 arguments.callee 类似的功能。使用 ...(rest) 参数之 前,应确保不需要使用 arguments.callee。 下面的示例使用 ...(rest) 参数(而非 arguments 对象)来重写 traceArgArray() 函数: function traceArgArray(... args):void{ for (var i:uint = 0; i < args.length; i++){ trace(args[i]); } } traceArgArray(1, 2, 3); // 输出: // 1 // 2 // 3 ...(rest) 参数还可与其它参数一起使用,前提是它是最后一个列出的参数。下面的 示例修改 traceArgArray() 函数,以便它的第一个参数 x 是 int 类型,第二个参数 使用 ...(rest) 参数。输出结果将忽略第一个值,因为第一个参数不再属于 由 ...(rest) 参数创建的数组。 function traceArgArray(x: int, ... args){ for (var i:uint = 0; i < args.length; i++){ trace(args[i]); } } traceArgArray(1, 2, 3); // 输出: // 2 // 3 1.5.6.3 函数作为对象 ActionScript3 中的函数是对象。当你创建函数时,就是在创建对象,该对象不仅 可以作为参数传递给另一个函数,而且还可以有附加的属性和方法。 作为参数传递给另一个函数的函数是按引用(而不是按值)传递的。在将某个函数作为 参数传递时,只能使用标识符,而不能使用在调用方法时所用的小括号运算符。例如,下面 的代码将名为 clickListener() 的函数作为参数传递给 addEventListener() 方 法: addEventListener(MouseEvent.CLICK, clickListener); Array.sort() 方法也定义了一个接受函数的参数。 阅几科技 - 36 - 尽管刚接触 ActionScript 的程序员可能对此感觉有些奇怪,但是,函数确实可以 像其它任何对象那样具有属性和方法。实际上,每个函数都有一个名为 length 的只读属 性,它用来存储为该函数定义的参数数量。该属性与 arguments.length 属性不同,后 者报告发送给函数的参数数量。回想一下,在 ActionScript 中,发送给函数的参数数 量可以超过为该函数定义的参数数量。下面的示例说明了这两个属性之间的区别,此示例仅 在标准模式下编译,因为严格模式要求所传递的参数数量与所定义的参数数量完全相同: function traceLength(x:uint, y:uint):void{ trace("arguments received: " + arguments.length); trace("arguments expected: " + traceLength.length); } traceLength(3, 5, 7, 11); /* 输出: 收到的参数数量:4 需要的参数数量:2 */ 你可以定义自己的函数属性,方法是在函数体外部定义它们。函数属性可以用作准静态 属性,用来保存与该函数有关的变量的状态。例如,你可能希望跟踪对特定函数的调用次数。 如果你正在编写游戏,并且希望跟踪用户使用特定命令的次数,则这样的功能会非常有用, 尽管你也可以使用静态类属性来实现此目的。下面的代码在函数声明外部创建一个函数属 性,在每次调用该函数时都递增此属性: someFunction.counter = 0; function someFunction():void{ someFunction.counter++; } someFunction(); someFunction(); trace(someFunction.counter); // 2 1.5.6.4 函数作用域 1.5.6.4.1 作用域链 无论何时开始执行函数,都会创建许多对象和属性。首先,会创建一个称为"激活对象 "的特殊对象,该对象用于存储在函数体内声明的参数以及任何局部变量或函数。由于激活 对象属于内部机制,因此你无法直接访问它。接着,会创建一个"作用域链",其中包含由 Flash Player 检查标识符声明的对象的有序列表。所执行的每个函数都有一个存储在内 部属性中的作用域链。对于嵌套函数,作用域链始于其自己的激活对象,后跟其父函数的激 活对象。作用域链以这种方式延伸,直到到达全局对象。全局对象是在 ActionScript 程 序开始时创建的,其中包含所有的全局变量和函数。 阅几科技 - 37 - 1.5.6.4.2 函数闭包 "函数闭包"是一个对象,其中包含函数的快照及其"词汇环境"。函数的词汇环境包括 函数作用域链中的所有变量、属性、方法和对象以及它们的值。无论何时在对象或类之外的 位置执行函数,都会创建函数闭包。函数闭包保留定义它们的作用域,这样,在将函数作为 参数或返回值传递给另一个作用域时,会产生有趣的结果。 例如,下面的代码创建两个函数:foo()(返回一个用来计算矩形面积的嵌套函数 rectArea())和 bar()(调用 foo() 并将返回的函数闭包存储在名为 myProduct 的 变量中)。即使 bar() 函数定义了自己的局部变量 x(值为 2),当调用函数闭包 myProduct() 时,该函数闭包仍保留在函数 foo() 中定义的变量 x(值为 40)。因此, bar() 函数将返回值 160,而不是 8。 function foo():Function{ var x:int = 40; function rectArea(y:int):int {// 定义函数闭包 return x * y } return rectArea; } function bar():void{ var x:int = 2; var y:int = 4; var myProduct:Function = foo(); trace(myProduct(4)); // 调用函数闭包 } bar(); // 160 方法的行为与函数闭包类似,因为方法也保留有关创建它们的词汇环境的信息。当方法 提取自它的实例(这会创建绑定方法)时,此特征尤为突出。函数闭包与绑定方法之间的主 要区别在于,绑定方法中 this 关键字的值始终引用它最初附加到的实例,而函数闭包中 this 关键字的值可以改变。 1.6 程序实例 1.6.1 创建一个受约束的布局 受约束的布局 每当用户改变应用程序的窗口大小时,你希望布局的组件能够自动地进行调节,改变它 们的大小和位置。受约束的布局方式能够实现这种效果。 创建受约束的布局,你必须将容器的布局属性设置为绝对方式 (layout="absolute")。 备注:帆布容器/canvas container 并不需要进行 layout=”absolute”的属性 设置,因为它默 认是绝对布局方式。 举个例子,如果你想在用户增宽程序的窗口时拉长 TextInput 文本框,你可以将控 阅几科技 件锚 定在容器的左右边缘上,使文本框的宽度由窗体来确定。 在 Flex 中,所有的约束都是被设置为与容器的相对距离,它们不可能被设置为相对 于 其它控件。 插入并放置组件 创建受约束布局的第一步是在容器中放置组件,并将布局属性设置为绝对值方式。为了 精确到象素,你可以直接设置 x 和 y 坐标,而不是在容器中拖拉组件。 1. 在导航视图中选择 File > New > MXML Application,创建一个名叫 Layout.mxml 的应 用程序。默认地,Flex Builder 将 Application 标签中的布局属性设置为绝对方 式。 2. 将 Layout.mxml 文件作为进行编译的默认文件,并在关联菜单中选择 Set As Default Application。 3. 在 MXML 编辑器的设计模式中,将 Label 控件和 TextInput 控件从组件视图中 (Window > Components)拖拉到 Layout.mxml 文件里。 - 38 - 阅几科技 4. 使用鼠标指针将 Label 控件和 TextInput 控件放置到距离容器顶端 60 象素的 地方。 5. 在 Flex 属性视图中,打开 Common and the Layout categories of properties。 如果你看到的是属性表格而不是预览视图,请点击视图工具条中的标准视图按钮 /Standard View button。 6. 在布局中选择 Label 控件,并在属性项中进行相应的设置: Text: Email X: 20 Y: 60 - 39 - 阅几科技 7. 在布局中选择 TextInput 控件,并设置相应的 TextInput 属性: X: 90 Y: 60 Width: 300 8. 切换到 MXML 编辑器源代码模式,在 Layout.mxml 文件中输入随后的 MXML 代 码: 9. 在标签后输入额外的内容,就象这样: 然后,点击工具条上的设计按钮来预览布局效果。它看起来就象这样: 10. 保存文件并运行。 - 40 - 阅几科技 11. 拖拉浏览器的边缘使之更大或更小。组件保持它们与窗体左/上边界的相对位置, 但 是它们并没有进行扩展或压缩。举个例子,如果你的窗体过于狭窄,那么发送按钮就会 看不 到,而 TextInput 控件和 TextArea 控件也会被拦住一部分。 接下来的一步是为控件设置布局约束,以便它们可以在程序窗体大小改变时进行调节。 - 41 - 阅几科技 定义布局约束 在布局中放置好组件后,你就可以进行布局约束的定义了。在 MXML 编辑器的设计模 式中,选择 TextInput 控件(用来输入电子邮件地址的)。 在 Flex 属性视图中,确保 Layout category of properties 是展开的。Layout category 中包 含了设置锚定的选项。 3. 为 TextInput 控件定义布局约束,在视图中选择左/右锚定框,并指定距离窗体 左边 缘 90,距离窗体右边缘 60,就象这样: 这些约束也可以通过 MXML 代码来实现: 4. 在编辑器的设计模式下,选择 TextArea 控件,为它设置四个角与容器的距离: Left: 90 Right: 60 Top: 90 Bottom: 190 在 Flex 属性视图中的布局分类里,TextArea 控件看起来就象这样: - 42 - 阅几科技 5. 在布局中选择 Button 控件,选择右/底锚定框,分别设置数值 60 和 150,就象 这样: 6. 保存文件,编译后运行。 7. 拖拉浏览器窗体的边缘使其更大或更小。举个例子,如果你使窗体更狭窄,Send 按 钮会向左边移动,同时 TextInput 和 TextArea 文本框会变得更加狭窄。 - 43 - 阅几科技 如果你使浏览器窗体更加宽大,Send 按钮会向右边移动,TextInput 和 TextArea 文本框 会变得更宽。 1.6.2 使用列表类控件 插入并放置控件 首先,创建一个简单的布局,在其中包含一个 ComboBox 控件和一个 submit 按钮。 1. 在导航视图中选定 Lessons 项目,选择 File > New > MXML Application 并 创建一个名 叫 ListControl.mxml 的文件。 2. 将 ListControl.mxml 文件设计为被编译的默认文件,并在关联菜单中选择 Set As Default Application from the context menu。 3. 在 MXML 编辑器的设计模式下,从组件视图中拖拉一个面板容器到布局上,并在属 性视图中设置相应的属性: - 44 - 阅几科技 Title: Rate Customer Service Width: 350 Height: 200 X: 10 Y: 10 4. 从组件视图中拖拉出其它所需的控件到面板容器中: ComboBox Button 5. 在布局中选择 ComboBox 控件,并在属性视图中对它的相应属性进行设置: ID: cbxRating X: 20 Y: 20 ComboBox 控件现在并没有显示任何项,你需要稍后装入它们。 6. 选择 Button 控件并进行相应在的属性设置: Label: Send X: 140 Y: 20 本例的布局在设计模式下看起来就象这样: 7. 切换到编辑器的源代码模式下,在 ListControl.mxml 文件中输入随后的 MXML 代码: 8. 保存文件,编译后运行。如下图所示: - 45 - 阅几科技 9. 点击浏览器中的 ComboBox 控件。 这时并没有显示任何项,因为你还没有定义它的数据提供者。 装载列表 你可以使用子标签来装载列表控件。标 签使你可以 用几种方法来指定列表项。最简单的方法就是指定一个字符串数据,就象随后所示。 1. 在编辑器的源代码模式下,在标签对中输入: Satisfied Neutral Dissatisfied 2. 保存文件,编译后运行。 3. 点击 ComboBox 控件去查看列表项。 - 46 - 阅几科技 如果你想要访问 ComboBox 控件中所选项的值,你可以使用随后的表达式: cbxRating.value 在本例中,ComboBox 控件(cbxRating.value)的 value 属性可以是 Satisfied, Neutral 或 Dissatisfied。 5. 为了测试控件,在 ListControl.mxml 文件中的标签中插入随后 内容: 波浪括号({ })里的表达式用来将 ComboBox 控件的数值属性,cbxRating.value 绑定 到 Label 控件的文本属性上。换而言之,Lable 控件的文本属性是由 ComboBox 控 件中的所 选项的数值来决定的。 6. 保存文件,编译后运行。 将列表项与数值相关联 将列表项与数值进行关联的方法与在你在 HTML 中使用 SELECT 一样。 使用一个对象组件数据来装载 ComboBox 控件。在标签中你定义了一 个 label 属性,它包含了在 ComboBox 中显示的字符串,以及想要进行关联的数据。 1. 在编辑器的源代码模式下,用随后的标签代替掉三个 标签: 如果你想要访问 ComboBox 控件中被选项的数值,你可以在代码中使用随后的表达式: cbxRating.value 2. 保存文件,编译后运行。 - 47 - 阅几科技 1.6.3 事件监听 创建一个简单的用户界面 你打算为在线商店创建一个简单的货币对换器,使用户可以将美元对换成等值的人民 币。要做的第一步是设计一个简单的用户界面。 1. 在导航视图中选定 Lessons 项目,选择 File > New > MXML Application 并 创建一个名 叫 Events.mxml 的文件。 2. 将 Events.mxml 设置为被编译的默认文件,并在关联菜单中选择 Set As Default Application。 3. 在 MXML 编辑器的设计模式下,从组件视图中拖拉一个面板容器到布局上,并设置 相应的属性: Title: Currency Converter Width: 450 Height: 150 X: 20 Y: 20 4. 从组件视图中拖拉两个 Label 控件,一个 TextInput 控件和一个按钮控件到面 板容器 中。 5. 布置这些控件,使布局看起来就象这样: 6. 选择第一个 Label 控件,将它的文本属性设置为 Price in Dollars。 7. 选择 TextInput 控件,并将它的 id 属性值设置为 txtPrice。 8. 选择按钮控件并进行相应的设置: ID: btnConvert Label: Convert to Yen 9. 选择第二个 Label 控件(位于 TextInput 控件下)并进行相应的设置: 清空它的文本属性值 将 lblResults 作为它的 id 属性值 10. 调整好控件的位置,使它看起来就象这样: - 48 - 阅几科技 11. 切换到源代码模式下,输入如下代码(你可以改变其中的坐标数值): 12. 保存文件。 编写一个事件监听器 接下来,为转换人民币按钮编写一个事件监听器。该事件监听器的 ActionScript 功 能函 数可以进行计算并以人民币为单位进行显示。 1. 切换到源代码模式下,在中放置插入点。 2. 输入直到整个标签在代码提示中被选定,按下 Enter 键在代码中插 入标 签,随后输入结束方括号。 脚本块包含了 CDATA 结构。 3. 在 CDATA 结构输入随后的代码: public function convertCurrency():void { var rate:Number = 120; var price:Number = Number(txtPrice.text); if (isNaN(price)) { lblResults.text = "Please enter a valid price."; } else { price = price * rate; lblResults.text = "Price in Yen: " + String(price); } } 4. 保存文件。 使用 MXML 将监听器与事件相关联 将一个监听器与一个事件相关联,或者注册它,就意味着在你的应用程序中包含了某种 逻辑,用来通知触发事件的监听者。 - 49 - 阅几科技 注册监听器的一种方法是在标签中将它指定为 click 的属性值。 同时,你还可以使用 ActionScript 去注册监听器。 1. 在设计模式下, 选择按钮控件并在属性视图中的 On Click 文本框中输入 convertCurrency()。 2. 保存文件,编译后运行。 3. 输入价格,并点击“Convert to Yen”按钮。 TextInput 控件下方的 Label 控件将以人民币为单位进行显示。 使用 ActionScript 将监听器与事件相关联 你还可以使用 ActionScript 将监听器与指定的事件相关联,如鼠标点击。每当事件 发生 时,监听器就被通报并开始运行。 1. 切换到源代码模式。 2. 删除标签中的 click 属性和它的数值。 3. 在 convertCurrency 事件监听器中声明一个事件对象,就象这样: public function convertCurrency(e:Event):void { ... 每当监听器的功能函数被调用时,Flex 创建一个事件对象并传递给监听器。因此,最 好 的办法是在监听器的功能函数中声明事件对象。因此,你在 convertCurrency 函数 中声明了 一个叫 e 的事件类型对象。 4. 在 标签中的 convertCurrency 函数前输入随后的代码: public function createListener():void { btnConvert.addEventListener(MouseEvent.CLICK, convertCurrency); } - 50 - 阅几科技 - 51 - 每当用户点击 btnConvert 按钮,convertCurrency 事件监听器就被通知相应的 触发事件已 经发生。监听器函数执行货币计算并显示结果。 脚本块看起来就象这样: 5. 在标签中,输入随后的属性值以便 createListener()功 能函数被调 用,并且使事件监听器在程序被创建后立即被注册: creationComplete="createListener();" 标签看起来就象这样: 6. 保存文件,编译后运行。 7. 输入价格并点击“Convert to Yen”按钮。 TextInput 控件下方的 Lable 控件将以人民币为单位进行显示。 1.6.4 Web服务 详见实例代码。
还剩50页未读

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 8 金币 [ 分享pdf获得金币 ] 0 人已下载

下载pdf

pdf贡献者

xuesheng32

贡献于2013-02-17

下载需要 8 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!
下载pdf