Flex入门

Flex入门指南—PHP开发者

作者: Mihai Corlan—Adobe Platform Evangelist

什么是Flex?

最简单的回答是:Flex仅仅是创建Flash应用程序的另一种方法。Flash应用程序是在SWF文件中编译的,并且由Flash Player在浏览器中进行播放。为什么我们需要使用另一种方法创建Flash应用程序?传统的Flash应用程序是使用Flash制作工具创建的。如果 你查看一下该工具,你会发现它主要适用于设计人员。其中包括一个舞台(stage),一条时间轴线(timeline)以及各种绘画工具等。

当你在开发应用程序并且追求开发效率时,你需要各种组件,你希望通过重用代码尽可能地提高开发效率,最后但并不是最不重要的一点是,你需要一个新型的IDE。

因此,一种修正的回答可能是:Flex是一种能够帮助开发人员快速创建富因特网应用程序(Rich Internet Application)的开源框架,这些应用程序能够在Flash Player中运行。在2006年的今天,随着Flex 2、Flash Player 9和 ActionScript 3的推出,该框架已经趋于定型。目前的版本是Flex 3,2010初,其下一个版本Flex 4将要面世。

 

Flex: 一个框架绑定的两种语言

在Flex之下,你将发现下列语言和工具:

  • 两种语言:MXML和ActionScript 3 。Flex提供两种语言以便创建Flex应用程序。在下面的章节中,我将进一步地讨论每种语言。
  • 一个富组件库
  • 各种编译器和调试器
  • 用于编译和调试Flex应用程序的各种命令行工具

由于Flex是一种开源框架,因此我极力推荐你访问该计划的主页 并且下载相关的SDK。你能够从组建库中查阅到所有组件的源代码,你能够查询相关的开放程序缺陷和功能库(http://bugs.adobe.com/flex),以及查看各种规范的wiki 页面。

Flex提供的部分效率改善应该归功于其海量组件库。该组件库包含了所有你能够想象的UI组件(例如,各种输入框(input box)、面板(panel)、视窗(window)、滑动条(slider)、数据网格(data grid)、组合框(combo box)、折叠显示(accordio)和Tab设置(tab set)等等)。另外,该组件库还包含各种布局容器和表单元素。在下面的图中,你能够看到Flex 3可以提供的各种UI组件的屏幕截图。


如果这些组件仍然不够使用,则你可以进入相应的源代码,扩展这些组件以创建你自己的组件或从零开始创建新的组件。

为什么你需要关注Flex

在深入探讨什么是Flex之前,让我们暂停一下,重温为什么你需要关注Flex的原因。

传统的HTML Web应用程序具有“请求-响应”架构。在浏览器发送一个请求之后,相应的服务器回送一个页面,这样的周期不断重复。HTML 和 CSS为呈现该信息提供了卓越的选择, 正如可提出证据加以证明的那样,这是目前最佳的选择之一。然而,随着时间的推移,这种架构不仅局限于静态呈现,而已经扩展至应用程序平台。利用脚本技术, 我们尝试创建动态页面以及设计服务器使得其能够对特定请求给出响应。更进一步地,通过添加DHTML 和AJAX ,我们能够将新的气息带入由Web服务器支持的页面:用户能够与载入页面互动并且在无需刷新整个页面的情形下改变相关的视图。

随着这些技术的演化,各种复杂的应用程序不断出现。一些Web应用程序已经开始复制许多桌面应用程序的功能而且同时能够保持Web应用程序的便利性(只要有浏览器和因特网连接的地方就能够使用Web应用程序)。因此,各种在线版本的电子制表软件和文本编辑器不断涌现。

然而,从可用性的角度来看,在线应用程序的用户友好界面要比桌面应用程序差。同时,如需创建这些复杂的Web应用程序,你必须掌握许多技术 (JavaScript、DHTML、CSS、AJAX 库以及服务器端等技术 )的各种技巧,并且你必须具有处理不同浏览器之间差异的经验以及了解他们是如何实现HTML/CSS/JS的。因此,2002年,Macromedia提 出了术语RIA(Rich Internet Applications)来描述一种结合了Web应用程序的优势和桌面应用程序的益处的新型应用程序。能够实现这一新型应用程序的技术就是Flash Player。

通常,如果你希望创建应用程序(而不仅仅是一个Web站点或Web页面),你可以使用Flex来实现。一些应用程序几乎不能使用 HTML/JavaScript来创建,而另外一些应用程序很难跨浏览器一致运行。Flash Player 能够提供最好的图形引擎,它已经安装于98% 的具有因特网连接的计算机,并且能够将声音和图像视为“一等公民”。它支持麦克风(microphone)和Web摄像(webcam)功能、支持流媒体 和数据推送(streaming and data pushing)服务、以及提供卓越的字体排印(typography)功能,其支持的功能可以填满很长的清单。

请看看下面三个应用程序以便了解使用Flex能够出现什么样的奇迹:

  1. SumoPaint 是一个免费使用的图像编辑应用程序;
  2. Mindomo 是一个思维导图应用程序;
  3. Times Reader 是一个源自《纽约时报》(The New York Times)的应用程序。

随着时间的推移,其他技术已经进入RIA领域。除了使得如Gmail 或 Google Spreadsheets 等应用程序成为现实的AJAX 不断发展之外,今天,我们还能够看到源自Microsoft的Silverlight应用程序以及源自Sun的JavaFX应用程序。

 

从瘦客户端向智能/富客户端演化

让我们回到浏览器以及Web应用程序是如何传送的。当浏览器发出一个请求,相应的服务器将使用静态内容(HTML/CSS/JS 代码)和脚本(这些脚本可能查询数据库或调用其他脚本,但最终他们会输出HTML/CSS/JS)的组合来准备一个页面。该页面由浏览器载入并且显示出 来。在此,一个关键元素是,通常该页面(或响应)具有显示标记(presentation markup )以及烘焙至相同消息的数据。

当应用程序的新状态需要呈现时,浏览器发出一个新的请求,之后相应的服务器将准备请求的页面。而客户端“仅仅”显示该数据。

Flex应用程序以不同的方式工作。服务器发送已编译过的Flex应用程序 (SWF 文件) ,该应用程序能够在浏览器中使用Flash Player插件运行。通常,该SWF文件只能支持客户端侧的业务逻辑。如果需要数据(例如来自数据库),则Flex应用程序能够发送请求以获得这些数 据。服务器只发送数据(数据的格式可以为XML、JSON或AMF3),并且客户端能够知道如何显示该数据。我们这里讨论的是面向服务的架构:

Flex应用程序实际上是客户端–一种能够使用由服务器提供的数据服务的客户端。该应用程序能够在浏览器不刷新页面或不重新装载SWF文件 的情形下变更状态。该应用程序是一种能够不仅仅显示数据的客户端。因此,通过利用Flex 和Flash Player能够创建几乎任何对象,这些对象对于在Web上部署各种游戏、应用程序以及widget具有重要意义,而这些游戏、应用程序以及widget 能够与“古典”Web应用程序以及其他应用程序进行集成。

到此为止,已经谈论太多的枯燥理论,让我们看看一些程序代码吧!

 

MXML语言简介

MXML是一种陈述性的、基于XML的语言。在Flex应用程序中,你可以使用MXML语言快速地创建应用程序的结构/外观。在Flex中,你使用MXML能够创建的应用程序,也可以使用ActionScript 3来创建。然而,反向操作不能成立。

如果你能够使用ActionScript 3来创建可以使用MXML完成的应用程序,那么为什么MXML会首先出现?通常学习和理解利用XML语言描述的用户界面比利用命令式语言描述的用户界面要 简单得多。这样利用XML语言编写的用户界面将会具有较少的代码。另外,为陈述性语言建立工具比为命令式语言也简单得多。下面是利用MXML实现的一个范 例“Hello world!”。

  1: <Label text="Hello World!" fontSize="14" color="red" x="100" y="50"/>

在这段代码中,我使用了一个名称为Label的Flex组件在屏幕上显示若干文本字符。我将文本的属性设置为我期望的文本格式。另外,我希望能够对 外观及该Label在屏幕上的位置进行(少许)客户化处理。因此,我使用了属性fontSize、color、x 和 y。我相信你会同意这是非常易于理解和学习的范例。

现在,考察一下利用ActionScript 3实现的相同范例:

 

  1: var myLabel = new Label();
  2: myLabel.text = "Hello World!";
  3: myLabel.setStyle("fontSize", "14");
  4: myLabel.setStyle("color", "red");
  5: myLabel.x = 100;
  6: myLabel.y = 50;
  7: addChild(myLabel);

 

我使用了7行代码来实现前面我仅用包含一个标记和若干属性的MXML实现的范例!现在,可以设想一下在一个真正的应用程序中,你采用大量的控件,并 且在不同的容器中进行分组。那么,维护利用MXML编写的代码要比维护使用几百行ActionScript 3编写的代码更为简单。

尽管你能够使用MXML描述你的应用程序,但你不能使用MXML实现你的应用程序的业务逻辑。而你可以利用ActionScript 3实现这一目的。

Flex应用程序能够运行于Flash Player,而Flash Player只能支持ActionScript 2 和ActionScript 3。这意味着你在应用程序中编写的任何MXML代码必须通过相应的MXML编译器转换成ActionScript 3代码。然后,该代码通过ActionScript编译器被转换成Flash Player支持的字节代码(bytecode)(SWF文件)。

因此,几乎每个MXML组件的后面均存在一个ActionScript 3类(实际上,有些MXML标记没有相应的ActionScript 类,例如Script 和 Model)。在下面的范例中,这是一个源自Label 类的一个代码片段( snippet ):

  1: public class Label extends UIComponent
  2:                    implements IDataRenderer, IDropInListItemRenderer,
  3:                    IListItemRenderer, IFontContextComponent
  4:
  5: {
  6:     /**
  7:      *  Constructor.
  8:      */
  9:     public function Label()
 10:     {
 11:         super();
 12:
 13:         // this is so the UITextField we contain can be read by a screen-reader
 14:         tabChildren = true;
 15:     }
 16:
 17:     /**
 18:      *  @private
 19:      *  Flag that will block default data/listData behavior.
 20:      */
 21:     private var textSet:Boolean;
 22:
 23: ...
 24: }

在任何Flex应用程序中,你应该至少具有一个MXML文件,这是主应用程序。例如,下面是“Hello World!” 应用程序的完整代码。

  1: <?xml version="1.0" encoding="utf-8"?>
  2: <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml

">
  3:         <mx:Label text="Hello World!" fontSize="14" color="red" x="100" y="50"/>
  4: </mx:Application>

根节点必须总是Application,而且这是定义命名空间的位置。在本范例中,我仅仅提供一个用于MXML语言和Flex组件的命名空间:mx(上面的代码是使用Flex 3编写的。如果使用Flex 4,则代码具有微小的差异,其中声明了多个命名空间)。

如果你编写自定义组件,则必须为其添加一个命名空间。例如,在下面的代码中,我声明了第二个命名空间指向我所创建的所有组件(在本范例中,我使用了一个我自己创建的名称为MyCustomLabel 的自定义label 组件):

  1: <?xml version="1.0" encoding="utf-8"?>
  2: <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml

" xmlns:local="*">
  3:     <mx:Label text="Hello"/>
  4:     <local:MyCustomLabel text="world!"/>
  5: </mx:Application>

到目前为止,你也许想知道Flex应用程序是如何处理不同页面的。对于HTML Web站点,通常不同状态是在不同页面实现的。而Flex应用程序与桌面应用程序非常相似。这意味着你只需使用一个MXML文件,即可在该页面上显示应用 程序的不同状态。Flex能够提供许多手段来实现这一目的,这些方法包括使用如折叠显示(Accordion)、Tab设置浏览器(Tabsets navigator)和牌布局管理器(Card layout)的Flex组件以及Flex模块等。

你已经看到MXML代码能够用于定义应用程序的外观。但你也能够利用它并且通过扩展现有Flex组件创建自定义组件。让我们来看一个范例。 假设在你的应用程序中具有若干表单,这些表单具有两个按钮:Save 和Cancel。观察一下该MXML自定义应用程序的代码(该代码是在一个名称为FormButtons.mxml的文件中创建的。所有MXML文件必须 使用mxml 扩展名)。

  1: <?xml version="1.0" encoding="utf-8"?>
  2: <mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml

" width="400" height="150">
  3:     <mx:Button id="saveButton" label="Save"/>
  4:     <mx:Button id="cancelButton" label="Cancel"/>
  5: </mx:HBox>

当你创建自定义应用程序时,你能够选择需要扩展的任何组件(但你不能对Application进行扩展)。我选择扩展HBox (Horizontal Box),这是一个能够在相同行显示所有children的容器。在该容器的内部,我添加了两个按钮,一个用于Save,另一个用于Cancel。我还为 每个按钮设置了id 属性。你可以使用id 属性值作为引用代码其他部分的对象的一种方式。这与在ActionScript代码中声明一个变量的方式是相同的。 现在,让我们看看你如何在一个Flex应用程序中使用该自定义组件:

  1: <?xml version="1.0" encoding="utf-8"?>
  2: <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml

" xmlns:local="*" layout="horizontal">
  3:     <mx:TextInput width="150"/>
  4:     <local:FormButtons/>
  5: </mx:Application>

你也许会认为在MXML中你只能使用视觉Flex组件(即最终能够被显示的组件)。实际上,这是不确切的。你可以使用表示数据的MXML标签(用于 存储数据的对象)或操作数据的组件(能够从服务器查询数据或向服务器发送数据的组件)。下面,你能够看到一个generic对象组件的范例,该组件具有一 个名称为name的特性(property):

  1: <mx:Object id="myObj" name="Mihai Corlan"/>

正如我前面所述的那样,与Flex相伴的所有(几乎所有)Flex组件均具有ActionScript类,该类能够实现视觉外观(如果有的话)以及 相应的逻辑。当你选择使用ActionScript 而不是 MXML创建一个自定义组件(不论其是否是视觉组件)时,你必须记住存在以下限制:在不带自变量的情形下,该类的构造器(constructor)必须能 够被调用(如果具有自变量,则这些自变量应该具有默认值)。

MXML简介

MXML和ActionScript 3之间的混合

返回到自定义组件FormButtons (具有两个按钮的组件),你也许注意到一个问题:如果你希望在一个Save 和 Cancel 标签不起作用的地方使用该组件将会怎样?你应该创建另一个带有你期望的标签(例如Show 和 Hide)的自定义组件吗?当然,这是一个选择,但这个组件不能缩放或外观不太优雅!你所真正期望的是一个更为通用的组件,以及一种使用代码变更组件的方 法。这是为什么迟早你不得不在MXML代码中添加ActionScript代码。

在下面的范例中,我在组件的MXML代码中添加了ActionScript代码以定义两个存储了按钮使用的标签的变量。注意,我使用了一个 新的标签Script,并且在该标签之中使用了CDATA。这是因为在XML文档之中,像>、<和& 等字符是非法的(如果它们没有换码)。另外,现在我将不会把太多重点放在ActionScript代码上,但我将在后面的章节中更深入地讨论 ActionScript代码。

  1: <?xml version="1.0" encoding="utf-8"?>
  2: <mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml
" width="400" height="150">
  3:     <mx:Script>
  4:         <![CDATA[
  5:             public var label1:String = "Save";
  6:             public var label2:String = "Delete";
  7:         ]]>
  8:     </mx:Script>
  9:     <mx:Button id="saveButton" label="{label1}"/>
 10:     <mx:Button id="cancelButton" label="{label2}"/>
 11: </mx:HBox>

我定义的变量可以在使用该组件的Flex应用程序中设置。下面,让我们来看看在使用新的自定义组件之后,变更的Flex应用程序代码的构成。

  1: <?xml version="1.0" encoding="utf-8"?>
  2: <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml
" xmlns:local="*" layout="horizontal">
  3:     <mx:TextInput width="150"/>
  4:     <local:FormButtons label1="Show" label2="Hide"/>
  5: </mx:Application>

注意,FormButtons 标签具有两个属性: label1和 label2。这是为什么你能够在这些按钮上设置期望显示的文本。并且这是你使用的机制以便将更多的行为添加至MXML组件(使用 ActionScript代码)。在真正的应用程序中,你可能希望将一个行为与每个按钮进行绑定,以便当按下按钮时,就会产生相应的结果。你可以使用 ActionScript代码编写通过按下按钮即可触发的各种函数。

另外,还有一种在MXML至添加ActionScript 代码的方法。你可以先创建一个ActionScript 文件(在本范例中,该文件的名称为buttons.as),然后将该文件包含于MXML文件中。你可以通过添加一个具有source 属性的 Script 标签实现这一操作 ,而该属性指向该ActionScript文件。下面是这一方法的代码。

  1: // ActionScript file called buttons.as
  2: public var label1:String = "Save";
  3: public var label2:String = "Delete";
  
  
  1: <?xml version="1.0" encoding="utf-8"?>
  2: 
  3: <mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml
" width="400" height="150">
  4:     <mx:Script source="buttons.as"/>
  5:     <mx:Button id="saveButton" label="{label1}"/>
  6:     <mx:Button id="cancelButton" label="{label2}"/>
  7: </mx:HBox>

现在,让我们后退一小步,然后推测一下当MXML编译器解析FormButtons.mxml 文件时会发生什么情况。你已经知道所有代码将会转换成ActionScript代码。但对于我添加的现有ActionScript代码(两个变量)会发生 什么情况呢?MXML编译器将会把每个MXML文件编译至一个ActionScript 类。在这种情形下,我将获得一个名称为FormButtons(因为这是该文件的名称并且它可以用于该类的名称)的类,该类扩展了HBox 组件(因为我选择了 HBox 作为该组件的根节点)。该类中的所有ActionScript代码将会变成该类的成员:变量(例如本范例中的变量)将会变成实例变量,并且函数将会变成实 例方法。

CSS式样

到目前为止,你也许想知道你是否能够改变视觉Flex组件的外观。Flex组件具有类似HTML CSS的技术?答案是肯定的,Flex 支持 CSS。在Flex 4中,对CSS的支持已经扩展至允许不仅可以基于类的名称而且可以基于ID进行式样定义,以支持伪选择符(pseudo-selector)(例如,对于 一个按钮来说,你应该具有下选择符(down selector)、上选择符(over selector)等等)以及其他更多功能。

与在HTML中一样,式样可以在行中(在MXML代码内部)定义或在一个独立的文件中定义。让我们先回到自定义组件 FormButtons, 然后设置若干式样。如果你选择在一个独立的文件中定义试样,则必须使用一个Style 标签并且将路径设置为 source 属性中的式样文件。

  1: <?xml version="1.0" encoding="utf-8"?>
  2: 
  3: <mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml
" width="400" height="150">
  4:     <mx:Style>
  5:         .Button1 {
  6:             font-size: 14;
  7:             color: #990000;
  8:         }
  9:     </mx:Style>
 10:     <mx:Script source="buttons.as"/>
 11:     <mx:Button id="saveButton" styleName="Button1" label="{label1}"/>
 12:     <mx:Button id="cancelButton" label="{label2}"/>
 13: </mx:HBox>

我创建了一个名称为Button1 的CSS类,该 CSS类定义了标签颜色以及字体大小。然后,我使用第一个按钮的styleName 属性将式样设置为第一个按钮。至此,该应用程序如下图所示:

CSS式样在运行时能够改变(在Flex应用程序载入浏览器之后),并且该应用程序的外观也会立即随着改变。

在Flex 4中,Adobe添加了名称为MXML用于图形的新语言,该语言添加了原语(primitive)、效果(effect)、面具( mask) 和2D 转换功能。你可以使用这些新的标签在MXML文件中创建皮肤(skin)类,然后你能够将该类设置为你期望对其进行皮肤粘贴的组件。在下图中,你能够看到 一串以Flex 4为皮肤的图像。左边给出了该串图像的默认状态,而右边给出了该串图像的打开状态。你可以点击这里 观看处于运行状态的应用程序。

当你在关于Flex应用程序外观的自定义的文档中徘徊时,你也许能够理解术语“皮肤粘贴”的含义。你可以进行图形皮肤粘贴 (graphical skinning )或编程皮肤粘贴(programmatic skinning )以便改变相应的外观。点击这里 可以获得关于这方面问题的佳文。

在运行时修改MXML代码

有时候你希望在运行时变更UI组件。也许你希望根据你从服务器中检索到的数据来实时地建立一个表单。同样,你也能使用ActionScript代码 实现这一任务。任何视觉Flex组件均具有添加一个新子类、移除一个新子类以及获取所有子类等方法。如果你愿意,你可以将这些方法与在HTML中使用 JavaScript改变DOM的方式进行比较。然而,它们之间存在差异:利用JavaScript你可以注入你从服务器检动态索到的HTML代码(通过 一个AJAX 调用)。但在Flex中,这是不可能,并且在Flex中不存在eval() 函数。然而,在主应用程序载入之后,有方法可以载入其它Flex应用程序或Flex模块。

当你了解一个组件的所有不同视图时,你能够使用MXML States 来实现相同组件或应用程序的不同状态。状态功能是Flex 4对比Flex 3的实现方式改善非常显著的地方,这使得这些状态更加易于使用并且添加更多功能。在Flex 4,状态的工作方式如下:

  1. 你可以定义若干状态并且指定默认状态
  2. 你能够指定在一个特定的组件应该出现在哪些状态中
  3. 你可以指定在状态出现的位置每个状态的任何属性的独立值

假设你希望创建一个处理应用程序登录功能的组件。你希望使用该组件显示登录表格,并且在登录成功之后,你希望显示退出按钮以及用户姓名。 下面是使用Flex 4创建的登录/退出组件:

  1: <?xml version="1.0" encoding="utf-8"?>
  2: 
  3:     <s:states>
  4:         <s:State name="notlogged"/>
  5:         <s:State name="logged"/>
  6:     
  7:
  8:     <s:TextInput includeIn="notlogged" text="user name"/>
  9:     <s:TextInput includeIn="notlogged" text="password"/>
 10:     <s:Button includeIn="notlogged" label="Login" click="{currentState='logged'}"/>
 11:
 12:     <mx:Label includeIn="logged" text="Current user: Mihai Corlan"/>
 13:     <s:Button includeIn="logged" label="Logout" click="{currentState='notlogged'}"/>
 14:     
 15:         <s:HorizontalLayout/>
 16:     
 17: </s:Group>

上面的代码应该是很容易理解的。作为顶部容器,我使用一个具有设置为HorizontalLayout 布局的Group组件(这与用于上面范例Flex 3中的Hbox具有相同的效果)。我已经在该文件的顶部为该组件定义了可用状态。接下来,我还定义了按钮、文本输入和标签。注意一下指定该组件在什么状态 下会出现的includeIn 属性。另外,文件中还包含一个excludeFrom 属性。如果你希望在所有状态下定义一个按钮,则无需为这两个属性指定任何状态。最后,你可以看到我为这两个按钮的点击属性指定了一个表达式。例如,表达式 click=”{currentState=’logged’}” 告诉Flex 当按钮被点击时,应该将该组件的状态改变为名称为logged的状态。

尽管我一直在讨论MXML语言,但我已经将越来越多的ActionScript代码加入了这些范例。这是一个迹象:该到讨论第二种Flex语言ActionScript 3的时候了。

ActionScript 3语言简介

ActionScript 3是一种动态的面向对象的脚本语言,它是(或几乎是)一种类型安全的语言。ActionScript 3 基于 ECMAScript 3 规范 (ECMA-262)。另外,其某些功能也是符合ECMAScript 4的相关建议。我已经发现采用下列方式对完全是ActionScript 3新手的开发人员解释该语言是最容易的:ActionScript 很像 JavaScript 和 Java的一个混合语言,并且其具有很强的个性。实际上,JavaScript是另一种基于ECMAScript 规范的语言,因此,其与ActionScript自然而然地具有许多共同点。

正如我前面所述的那样,Flash Player 能够运行两种语言:ActionScript 2 和ActionScript 3。Flash Player在其内部使用两种不同的虚拟机(Virtual Machine)来协调这两种语言(ActionScript 3 和 AVM2 Virtual Machine 是在 Flash Player 9中推出的)。ActionScript 3 是由核心语言(关键字和数据类型等 ) 以及 Flash Player API (该API 使得开发人员能够通过显示列表API( display list API)、3D API、绘画API(drawing API)以及动画(Animation)等API使用所有Flash Player 功能)构成的。在本文中,我将侧重讨论核心语言。点击 这里 ,你可以获得一篇关于ActionScript 3的入门佳文。

从现在开始,我将使用缩写“AS3” 替换 “ActionScript 3”。

隔离语句

在PHP语言中,你可以使用分号(;) 来隔离或结束一条语句。而在AS3语言中,你可以使用分号(;) 或仅仅行尾符。但我必须说,当我看到不用分号编写的代码时,我的眼睛将不会出现喜悦的目光。因此,我建议你使用与PHP使用的相同方法。

数据类型、变量和常量

PHP具有下列数据类型:布尔(Boolean)、整数(integer)、浮点数( floating point number)、字符串( String)、数组(Array)、对象( Object)、资源( Resource)和 NULL。

对于AS3来说,我们具有下列数据类型:

  • 顶级数据类型:布尔(Boolean)、整数(int)、单元(uint)、数( number)(与PHP的浮点数相同)、字符串( String)、Null (仅包含一个值:null)和void (仅包含一个值:undefined)
  • 复杂数据类型:对象( Object)、数组(Array)、矢量(Vector )(以 Flash Player 10开头)、字典(Dictionary)、位图(Bitmap)、字节数组(ByteArray)、日期(Date)、XML、XMLList、函数 (Function)、错误(Error)和RegExp等。

在AS3语言中,一个变量就是与实际值关联的一个标识符或指针。AS3中的合法值可以是对象(int 或 uint 是对象,Number 或 Date也是对象)、null 和undefined。null 和undefined均表示数据缺失,但它们之间存在差别。当你声明一个变量并且你没有对其初始化时,并且如果变量的类型不是Boolean、int、 uint或 Number,则该变量具有值null 。如果变量没有赋予数据类型并且没有初始化,则该变量具有值undefined。同时,当你拥有一个动态对象并且希望检查一个特定的方法或特性 (property)是否被定义时,你可以对undefined进行检查。

在PHP中,你可以按照下面的方式声明一个变量:

  1: $anInteger = 12;
  2: $isTrue = true;
  3: $aString = "my string";
  4: //or
  5: $aString = 'my string';

在AS3中,你可以使用var 关键词声明一个变量:

  1: var anInteger:int = 12;
  2: var isTrue:Boolean = true;
  3: var aString:String = "my string";
  4: //In AS3 you can not use simple quotes for declaring a String

注意在该变量名称之后,我添加一个类型注解;例如,myVarName:Boolean (该类型是使用 “:” 声明的,后面紧跟相应的类型)。在AS3中,你可以使用类型注解,也可以不使用类型注解(如果编译器设置为严格模式(strict mode ),则你必须使用类型注解)。

对于PHP来说,你不必声明变量的类型,因此,这一点也许显得奇怪,而且你可能希望坚持使用不指定类型的方式编写程序。由于使用类型注解具 有诱人的优点,我强烈推荐你使用类型注解。首先,当你使用IDE编写代码时,对变量进行分类将使得你在编译时发现更多错误。例如,设想具有一个单一 String自变量的函数。如果你试图调用该函数,将一个Object作为自变量进行传递,则IDE将提醒你这是错误。

如果不使用类型注解,你可能会遇到运行时错误,但只能在你或最终用户运行该应用程序时才会发现,并且此时查明软件缺陷的根源将会非常困难。

坚持使用类型注解的第二个原因是,如果AS3编译器知道变量的特定类型,则其能够对应用程序进行优化。

在PHP中,你能够利用每次赋值改变变量的类型:

  1: $myVar = 12; //it is an int
  2: $myVar = "now is a string";

在AS3中,只有当你使用“*”声明变量为untyped 时,你才能够完成相同当操作(使用严格模式)。

  1: var myVar:int = 12;
  2: //this will raise an error and the application can not be compiled
  3: myVar = "this is a string";
  4:
  5: //declaring the variable untyped you can change the type with each assignment
  6: var myVar2:* = 12;
  7: myVar2 = "this is a string now";

你可能注意到只有当声明变量时我才使用关键词var。对于下一步赋值操作,你可以忽略var 和类型注解。

正如我前面所述的那样,在AS3中变量仅仅是实际值的指针。然而,当你将int、uint、Number、Boolean或 String 变量赋值给另一个变量时,将会创建一个副本(对于将这些类型的一个变量传递给一个函数时,情况也是相同的)。在PHP中,你可以使用 “&” 运算符通过引用为原语类型进行变量赋值;当你为一个变量改变值时,其它变量将指向相同的改变值。

在PHP中,你使用“.” (dot)对字符串进行串接,而在AS3中,你可以使用“+” (plus)完成相同的任务:

  1: //in PHP
  2: $space = " ";
  3: $a = "this" . $space . "is!";
  4:
  5: //in AS3
  6: var space:String = " ";
  7: var a:String = "this" + space + "is!";

在PHP中,你可以在任何你期望的位置定义变量:例如在文件级、在函数中或在类中。在Flex应用程序中,变量只能在函数中或类级别中声明。

此外,在PHP中,你可以编写一段没有在函数中声明的过程化程序代码(procedural programming ):

  1: <?php
  2:
  3: $a = 1;
  4: for ($i=0; $i<100; $i++) {
  5:     $a += $i * $a;
  6: }
  7:
  8: ?>

在AS3中,你不能利用函数之外的变量进行任何操作(尽管你可以在函数之外声明变量),但有一个例外,我将在Class章节讨论它。因此,如果你试图运行下面的代码,你将在编译该应用程序时出错。

  1: <?xml version="1.0" encoding="utf-8"?>
  2: <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml
" layout="absolute">
  3:     <mx:Script>
  4:         <![CDATA[
  5:         var a:int = 1;
  6:         for (var i:int = 0; i<100; i++) { //this raises an error
  7:             a += i * a;
  8:         }
  9:         ]]>
 10:     </mx:Script>
 11: </mx:Application>

这是你为什么你可以通过重写该代码以便其能够正常运行:

  1: <?xml version="1.0" encoding="utf-8"?>
  2: <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml
" layout="absolute">
  3:     <mx:Script>
  4:         <![CDATA[
  5:         var a:int = 1;
  6:
  7:         function calculations(a:int):int {
  8:             for (var i:int = 0; i<100; i++) {
  9:                 a += i * a;
 10:             }
 11:             return a;
 12:         }
 13:         ]]>
 14:     </mx:Script>
 15: </mx:Application>

在PHP中,可以按照下面方式声明和使用常量。

  1: //constants
  2: define("CONSTANT", "Hello");
  3: $myString = CONSTANT . ‘ world!’;

在AS3中,可以使用const 关键词声明常量(使用大写字母命名常量是一个惯例):

  1: static const HELLO:String = "Hello";
  2: var myString:String = HELLO + " world!";

什么可以用于变量的名称呢?对于PHP和AS3来说,这一点是相似的:只要名称的第一个字符为字母或在“_”之后跟随字母、数字或下划线,该名称即为合法名称。对于两种语言来说,下面均是合法变量名称的范例:_1, _a1A, b。 在PHP中,通过了解其字符串名称,你可以使用该变量:

  1: <?php
  2: $myVar = 12;
  3: $varName = 'myVar';
  4: echo($$varName); //print 12;
  5: ?>

在AS3中,通过使用引用成员的动态方法(变量/方法),你可以获得相似的功能:

  1: <?xml version="1.0" encoding="utf-8"?>
  2: <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml
" layout="absolute" creationComplete="init()">
  3:     <mx:Script>
  4:         <![CDATA[
  5:
  6:             var myVar:int = 12;
  7:
  8:             function init():void {
  9:                 var varName:String = "myVar";
 10:                 trace(this[varName]); //output 12
 11:             }
 12:         ]]>
 13:     </mx:Script>
 14:
 15: </mx:Application>

在该范例中,我使用了this 来引用当前对象,但你可以对任何对象使用相同对技巧。当讨论动态类时,我将用更多当篇幅来对此进行说明。

函数和匿名函数(闭包)

在AS3中,你可以利用函数实现你可以在PHP中实现的每一件事,甚至更多事情。首先,在AS3中,你可以定义自变量类型和返回类型(在PHP中,你只能从对象添加类型注解至方法)。

  1: function calculate(x:int=0, y:int=0):int {
  2:     return x + y;
  3: }
  4: //using the function
  5: var result:int = calculate(1, 2);
  6:
  7: function calculateAverage(...arguments):Number {
  8:     var result:Number = 0;
  9:     for (var i:int=0; i<arguments.length; i++) {
 10:         result += arguments[i];
 11:     }
 12:     return result/arguments.length;
 13: }
 14:
 15: //using the function 
 16: var result:Number = calculateAverage(1, 2, 3, 4, 5, 6);

你可以将… (rest) 运算符与显示自变量进行混合,只要你将… (rest) 运算符作为自变量列表的最后一个元素放置即可:function foo(x:int, y:int, …arguments):Number {}。当你希望利用自变量中的一个变量成员创建函数时,… (rest) 运算符是非常有用的。

如果函数无需返回任何值,你可以使用void 作为返回类型。

在PHP和AS3中,你可以为自变量提供默认值。例如:

  1: //php code
  2:
  3: function doThing($a, $b="default value") {
  4:     echo $a . $b;
  5: }
  6:
  7: //AS code
  8: function doThing(a:String, b:String="default value"):void {
  9:     trace(a + b);
 10: }

当然,你可以在函数中定义函数(你将在下一个代码样本中看到一个范例)。

其次,在AS3中,任何函数将被表示为Function 类的一个实例。这使得某些有趣的事成为可能:

  • 你可以创建一个文字函数并且将它赋值给一个变量,然后通过该变量调用该函数(这在PHP中也能够实现)。
  • 你可以返回一个函数作为另一个函数的执行结果。
  • 当调用其它函数时,你可以将函数作为自变量传递。
  1: var f:Function = function multiply(x:int, y:int):int {
  2:     return x*y;
  3: }
  4:
  5: trace(f(3,5));
  6:
  7: function giveMeAFunction():Function {
  8:     return function multiply(x:int, y:int):int {
  9:         return x*y;
 10:     };
 11: }
 12:
 13: var h:Function = giveMeAFunction();
 14: trace(h(3,4));

在PHP和AS3中,你可以创建匿名函数(闭包)。在前面的代码样本中,你能够看到一个在giveMeAFunction() 中创建一个匿名函数然后将其返回的范例。

也许AS3和PHP的函数之间的最大不同点是你定义它们的方式。在PHP中,你可以在文件中定义任意数量的函数。而在AS3中,你在一个文 件中只能定义一个函数,并且该函数的名称必须与文件的名称相匹配。例如,如果你定义的函数的名称为doSomeMath(),则你必须在一个名称为 doSomeMath.as的文件中创建该函数。在定义函数时,你可以使用类包声明(package declaration)(你将在下一章节学习与包相关的内容)。因此当你希望创建大量工具函数,如果你不希望在大量文件中编写这些代码,则你可以创建一 个单一类然后将它们定义为静态方法。

OOP:类和接口

现在是讨论PHP和AS3的面向对象编程(Object Oriented Programming )功能的时候了。在PHP中,你可以编写面向对象或程序化的代码;而AS3是面向对象的语言。

让我们从简单PHP类开始来看看语法的不同点(记住我使用PHP 5.3作为编程参考语言):

  1: namespace org\corlan {
  2:
  3:     class SimpleClass {
  4:
  5:         public $public = 'Public';
  6:         protected $protected = 'Protected';
  7:         private $private = 'Private';
  8:
  9:         function SimpleClass() {
 10:
 11:         }
 12:         // Redefine the parent method
 13:         function displayVar()
 14:         {
 15:
 16:         }
 17:     }
 18: }
 19:
 20: //use the class like this
 21: require_once('flassFile.php');
 22: $obj = new org\corlan\SimpleClass();
 23: $obj->displayVar();

在AS3中,相同的类编写如下:

  1: package org.corlan {
  2:
  3:     public class SimpleClass {
  4:
  5:         public var _public:String = "Public";
  6:         protected var _protected:String = "Protected";
  7:         private var _private:String = "Private";
  8:
  9:         function SimpleClass() {
 10:
 11:         }
 12:
 13:         // Redefine the parent method
 14:         public function displayVar():void
 15:         {
 16:
 17:         }
 18:     }
 19:
 20: }
 21:
 22: //you use the class like this:
 23: import org.corlan.SimpleClass;
 24:
 25: var object:SimpleClass = new SimpleClass();
 26: object.displayVar();

下面是它们的主要差异:

  • 对存储类的文件进行命名
  1. 在PHP中,你可以在一个文件中定义一个类,而该文件可以以任意方式命名
  2. 在AS3 中,文件的名称必须与类的名称相同 (如果类的名称为 SimpleClass,则文件的名称必须为SimpleClass.as)
  • 命名空间 vs 类包
  1. 在PHP中,你可以使用命名空间以避免类之间的名称冲突
  2. 在AS3 中,你可以使用类包;然而,例如,当你在org.corlan类包中声明一个类时,这意味着该类将会包含于Flex源文件夹的 org/corlan文件夹中。该包名可以转变为一个文件夹结构。与类访问修饰符( class access-modifier)一起使用的类包能够将该类隐藏至项目之外的类中(后面将会详细讨论)。
  • 要求/包含vs. 导入
  1. 在PHP中,通常你可以使用require_once 函数包含定义类的文件。从PHP 5 开始,你将能够定义一个__autoload() 函数,并且在该函数中包含 require_once 或 include_once,而不需在每个文件的顶部编写一个要求的文件的列表 。
  2. 在AS3 中,你可以使用导入语句来包含期望的类。然而,如果你希望从类包 org.corlan中包含所有类,你可以使用一个通配符编写该导入语句:import org.corlan.*。另一个不同之处是AS3 编译器只编译那些在你的代码中实际使用的类 (即只有在特定类的一个实例被实际创建的情形下) 。
  • 调用方法/实例成员:
  1. 在PHP中,你可以使用 “->” 运算符
  2. 在AS3 中,你可以使用“.” (dot) 运算符

现在,让我们来讨论类/方法/成员修饰符。

我将从类修饰符开始讨论:

  • PHP 具有final和 abstract类修饰符;而public是隐式类修饰符,在PHP中,所有类均为public。
  • AS3 具有public、internal、final和dynamic类修饰符。如果你没有指定任何访问修饰符(public 或 internal),则该类默认为internal,其含义为该类只能被来自相同类包的类访问。public 和 final 与 PHP具有相同的含义。abstract 在AS3中不存在,但你可以使用接口克服这一限制。Dynamic 标示相应的类通过修改现有成员或添加新的成员能够在运行时进行更改。

类特性(class property)修饰符:

  • PHP 具有 public、private、protected和static修饰符。
  • AS3 具有 PHP 修饰符加上 internal修饰符。Internal 可用于使得特性(property)只能在相同类包的内部才是可用的。当没有指定修饰符时,可以使用internal 修饰符。

类方法(class pmethod)修饰符:

  • PHP 具有 public、private、protected、static、final和abstract修饰符。
  • AS3 具有public、private、protected、static、final、internal和override修饰符。abstract 在AS3中不存在;Internal 可以使得方法只能在相同类包的内部的代码中才是可用的。

在AS3中,你可以使用函数闭包实现的每一件事均可以使用类函数实现。

PHP的构造器可以标示为private,你可以定义一个具有与类名称相同的构造器,或你可以使用特定的方法__construct()和 __destruct()。在AS3中,构造器总是具有public修饰符并且必须具有与类相同的名称。如果没有提供任何修饰符,则AS3将为你在场景之 后创建一个修饰符。

静态成员或静态方法是可以访问的:

  • 在PHP中,使用ClassName::propertyName。
  • 在AS3中,使用ClassName.propertyName。然而,在相同类的内部,你可以省略该类名称。
  1: package org.corlan {
  2:
  3:     public class Foo {
  4:
  5:         private static myVar:String;
  6:
  7:         function Foo() {
  8:             Foo.myVar = "value 1";
  9:             myVar = "value 2";
 10:         }
 11:
 12:     }
 13: }

这里:

  • 在PHP中,你可以使用特别的类变量$this 来指向在相同类中定义的类成员(变量/方法): $this->myVar = 22。
  • 在AS3中,你可以使用相同的this:this.myVar = 22;然而,你可以忽略this, 然后仅使用myVar = 22即可。

在AS3中,只有一个类能够在类包的内部进行声明(一个this类可以给出该文件的名称)。然而,在类包声明的外部,你可以声明任意数量的类:

  1: package org.corlan {
  2:
  3:     public class Foo {
  4:
  5:         private static var instance:Foo;
  6:
  7:         function Foo(object:Bar) {
  8:
  9:         }
 10:
 11:         static public getInstance():Foo {
 12:             if (Foo.instance == null) {
 13:                 Foo.instance = new Foo(new Bar());
 14:             }
 15:             return Foo.instance;
 16:         }
 17:
 18: }
 19:
 20: class Bar {}

这将产生一个有趣的效果:所有在类包外部的文件中定义的类将只能在相同文件内部声明的代码中使用。对于所有其它代码,这些类不存在。记住AS3的限 制,即你不能声明该构造器为private。因此,通过使用与该范例相似的方法,你可以确保只存在一个Foo 类的实例。如果某外部代码调用该构造器时,系统将抛出一个运行时异常,因为外部代码不能使用Bar的实例并且该类对于外部代码是不可见的。

继承

在AS3中进行类的扩展与在PHP中非常相似。你可以使用相同的extends 关键词后面跟随你希望扩展的类的名称。覆盖(Overriding)功能与PHP相同,有一点不同之处是你必须将override 关键词添加至方法签名。AS3不支持重载(Overloading)功能(你不能拥有两个或更多具有相同名称的方法)。

在PHP中,你可以使用语句parent::memberName访问父成员;而在AS3中,你可以使用语句 super.memberName访问父成员。当执行一个类的构造器时,首先应该调用父构造器。甚至当你没有从你的代码中显式调用父构造器时也会发生父构 造器调用。因此,当你在构造器方法中编写代码时,你不能在你的代码之后放置父构造器的调用语句。这样,你可以为父类的正确初始化提供了机会,因此子类将不 会使用没有设置的成员。你可以使用语句super()调用父构造器。让我们来看看这些工作原理,先看PHP代码,然后再看AS3代码。

  1: class SimpleClass {
  2:
  3:     function SimpleClass() {
  4:         echo('SimpleClass() called');
  5:     }
  6:
  7:     function __construct() {
  8:
  9:     }
 10:
 11:
 12:     function displayVar()
 13:     {
 14:         echo "SimpleClass class\n";
 15:     }
 16: }
 17:
 18: class ExtendClass extends SimpleClass {
 19:
 20:     function ExtendClass() {
 21:         $myVar = 1;
 22:         parent::SimpleClass();
 23:         //or
 24:         parent::__construct();
 25:     }
 26:     // Redefine the parent method
 27:     function displayVar()
 28:     {
 29:         echo "Extending class\n";
 30:         parent::displayVar();
 31:     }
 32: }
  1: public class SimpleClass {
  2:
  3:     function SimpleClass() {
  4:         trace("SimpleClass() called");
  5:     }
  6:
  7:     public function displayVar():void
  8:     {
  9:         trace("SimpleClass class");
 10:     }
 11: }
 12:
 13: public class ExtendClass extends SimpleClass {
 14:
 15:     function ExtendClass() {
 16:         super(); //we have to call first the parent constructor, and only after we can execute our code
 17:         var myVar:int = 1;
 18:     }
 19:
 20:     override public function displayVar():void {
 21:         trace("overrided displayVar()");
 22:         super.displayVar();
 23:     }
 24: }

让我们看一下在AS3中类是如何初始化的。当一个类被例示时,首先其所有的特性(property)将被初始化,其次在类级别定义的静态代码将被执行(这在PHP中是不能执行的),最后构造器将被执行。下面是范例代码:

  1: public class Foo {
  2:
  3:         private var a:int = 0;
  4:         private static var os:String;
  5:         trace("initializer");
  6:
  7:         if (Capabilities.os == "LINUX")
  8:             os = "LINUX";
  9:         else
 10:             os = "other";
 11:
 12:         public function Foo(a:int=1) {
 13:             trace("foo() executed");
 14:         }
 15: }
 16:
 17: var foo1:Foo = new Foo();
 18: var foo2:Foo = new Foo();
 19: //produces this output in console:
 20: initializer
 21: foo() executed
 22: foo() executed

在AS3中,你可以使用函数的原型特性(property)创建函数闭包之外的对象(这与你在JavaScript中使用的函数来创建/扩展类的情况是相似的)。下面是一个简短范例代码:

  1: //we create a function
  2: function MyClass(value:String = "Mihai") {
  3:     //we create a property
  4:     this.name = value;
  5: }
  6: //we use the special variable prototype of the function 
  7: //to create another method 
  8: MyClass.prototype.setName = function (value:String):void {
  9:     //we have access to the property defined on MyClass object
 10:     trace(this.name);
 11:     this.name = value;
 12:     trace(this.name);
 13: }
 14:
 15: //create an instance
 16: var myObject = new MyClass();
 17: //accesing the method created earlier
 18: myObject.setName("Joe");

在后面的章节中,我将更多地讨论AS3的动态功能。

Getters/setters

在任何OOP语言中,你通常会使用getters/setters来控制你希望向外部暴露的类特性(property)。PHP也不例外。然而,在AS3中,可以使用关键词set 和 get对类特性(property)提供特别支持。下面是范例代码:

  1: public class Employee {
  2:
  3:     private var _salary:int = 0;
  4:     private var _income:int = 0;
  5:
  6:     function Employee() {
  7:
  8:     }
  9:
 10:     public function set salary(value:int):void {
 11:         if (value > 0) {
 12:             this._salary = value;
 13:             this._income = this._salary * 12;
 14:         }
 15:     }
 16:
 17:     public function get salary():int {
 18:         return this._salary;
 19:     }
 20:
 21:     public function get income():int {
 22:         return this.income;
 23:     }
 24: }
 25:
 26: //using this class
 27: var emp:Employee = new Employee();
 28: emp.salary = 1000;
 29: trace(emp.income);
 30: //this raise an error, because the income property is read-only 
 31: //for the outside code
 32: emp.income = 120;

通常,尽管我使用setter 和getter替代_salary 字段 ,但我可以调用这些方法,好像它们就是字段或特性(property)而不是函数:以object.salary = 20 替代object.salary(20)。如果你选择不对setter进行定义,你可以获得只读特性(property)。这就是我使用_income 特性(property)所实现的功能。

除了使得代码简洁一些之外,该功能还使得编写可以被其它应用程序使用的API或类更为简单。假设在我的范例中,我选择创建_salary 字段作为一个public成员。如果后来我决定需要验证能够设置的值,则我必须添加一个setter。在PHP中,这可能需要使用如 myObject.setSalary()的语句。此时,任何使用该类的代码将会被破坏;因此,代码必须使用setter进行更新。

在AS3中,你可以利用定义为public var salary:int 的特性(property)来启动该类,并且当你决定需要一个setter时,你可以对该变量重新命名,然后添加public function set salary() 方法。使用该类的任何代码将不受这一变更的影响,因为它仍然使用相同的语句objectInstance.salary = 10来访问该特性(property)。

在AS3中,当使用这种式样的setter 和getter时,有一个惯例是在变量名称前添加一个下划线。

接口

在PHP和AS3中,接口的工作方式几乎相同。一个显著的差异是在PHP中,你可以定义方法以及常量,而在AS3中,你只能定义方法。然而,你可以定义setter/getter:

  1: public interface IEmployee {
  2:
  3:     public function set salary(value:int);
  4:     public function get salary():int;
  5:     public function get income():int;
  6: }

异常

正如在PHP中的那样,AS3能够支持异常处理:

  1: try {
  2:
  3: } catch(e:Error) {
  4:
  5: } finally {
  6:
  7: }
  8:
  9: //throwing an exception
 10: throw new Error("Some error");

在AS3中,对于所有错误来说,Error 是顶级类。你可以创建自己的错误以扩展该类,或你可以使用现有的子类。

对象类型的转换和测试

有时,你希望将一个对象强制转换为一种不同的类型,或希望检查对象类型。在PHP中,你可以使用instanceof检查对象的类型,而在AS3中,你可以使用is检查对象的类型。为了进行类型强制转换,在AS3中,你可以使用两种不同的语句。

  1: class A {};
  2:
  3: class B extends A {};
  4:
  5: var b:A = new B();
  6: //casting
  7: var c:B = b as B;
  8: //or
  9: var d:B = B(b);
 10:
 11: //checking the type of an variable
 12: if (b is A)
 13:     trace(true);
 14: if (b is B)
 15:     trace(true);

变量作用域

前面我们已经了解了变量、函数和类是如何在Flex 和AS 3中工作的,现在是讨论变量作用域的时候了。在PHP中,通常你具有两个作用域:全局(global)(在文件级别定义的变量)和本地(local )(在函数内部定义的变量)。

在Flex中,共有5个作用域:函数体(function body)、实例方法体(instance method body)、静态方法体( static method body)、类体(class body)和全局作用域(global scope)。向这些作用域添加访问修饰符(public/private/protected/internal)使得事情比在PHP中变得更为复杂。

作用域可以嵌套。在本例中包含的作用域的变量/函数/成员均可以被嵌套的变量/函数/成员使用。例如,当你在另一个函数体的内部声明一个匿 名函数时,在AS3中,所有在外部函数定义的变量可以在嵌套函数的内部使用。在PHP中,你必须传递你希望使用的变量,或添加use 语句:

  1: //php code
  2: function a() {
  3:     $a = 1;
  4:     $b = 2;
  5:
  6:     function b() use ($a, $b) {
  7:
  8:     }
  9: }
 10:
 11: //AS3 code
 12: function a():void {
 13:     var a:int = 1;
 14:     var b:int = 2;
 15:
 16:     function b():void {
 17:         //variables a and b are available here
 18:     }
 19: }

当你在一个未命名类包的内部声明一个函数时,其将被放置在全局作用域之中并且其对所有代码均为可用的。然而,尽管在一个类包之外声明的任何函数仍然位于全局作用域,但其只能对来自相同文件对代码是可见的。

数组

在AS3中,数组与PHP的情况非常相似,仅有一处差异:在AS3中,一个数组仅具有数字下标。如果你希望创建一个关联数组,你可以使用 Object 类。如果你希望创建一个key是对象(而非字符串)的哈希图(hash map)时,你可以使用Dictionary类。你可以使用Array 类创建数组,也可以创建多维数组。对于Object 和Array ,你均可以使用文字定义。让我们来看看若干范例:

  1: var myArray1:Array = new Array(1, 2, "some string");
  2: //creates an array with three elements: 0->1, 1->2, 3->some string
  3:
  4: //literal definition for an array
  5: var myArray2:Array = [1, 2, 3];
  6: //ading two more elements
  7: myArray2.push(4,5);
  8:
  9: //a hash map, similar to associative arrays in PHP
 10: var myMap:Object = new Object();
 11: myMap.name = "Flex";
 12: //literal definition of a map
 13: var myMap2:Object = {name:"Flex"};
 14:
 15: //using Dictionary class
 16: var dic:Dictionary = new Dictionary();
 17: var anObject:Object = new Object(); //creating the key
 18: dic[anObject] = "some value"; //adding a value to Dictionary

你具有添加元素或删除元素的所有期望的方法,包括push、shift、pop、unshift和 splice。Concat 可以用于将数组添加至另一个数组。在前面的范例中,你可以看到我是如何使用 push 来添加另外两个元素至一个数组。 数组具有不固定的长度。其长度随着你添加更多元素而增加。在PHP中,你可以使用“[]” 在数组的结束部分添加一个新的元素。AS3具有相似的方法,该方法使用数组的length 特性(property )(你也能够使用length 特性(property )来声明数组的长度)。

  1: var array:Array = new Array();
  2: array[array.length] = 1;//array has the values: 1
  3: array[array.length] = 23;//array has the values: 1, 23

你可以使用delete 将数组的一个特定元素设置为undefined:delete array[index]。这一操作将不会缩短数组的长度。你可以使用for() 语句并且利用其length 特性(property )对数组进行循环操作。如果你希望对一个Object进行循环操作(这可以用于创建与PHP关联数组相似的数组),你可以使用for – each (其工作方式与PHP中相同的构造器相似) 或 for – in 语句(在 动态(Dynamic)章节将会更多地对其进行讨论 )。

命名空间

如果你希望寻找与PHP命名空间对等的AS3概念,你

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值