4.2. Differences Between Flash ActionScript and Server-Side ActionScript
As alluded to earlier in this chapter and the Preface,
there are two distinct types of ActionScript: client-side
ActionScriptwhich includes both ActionScript 1.0 and
ActionScript 2.0and the server-side version, known as
Server-Side ActionScript. Client-side ActionScript is used to create
.swf movies, which run in the Flash Player on
the user's machine. Server-Side ActionScript is
stored in .asc files that run on the FlashCom
Server.
Since Flash 5, client-side ActionScript has been based on the
ECMA (European Computer
Manufacturers Association) standards, as is JavaScript. The standard
language is named
ECMAScript and is
defined in ECMA-262 available at: http://www.ecma-international.org.
Client-side Flash ActionScript has never completely conformed to the
ECMAScript standard because Macromedia developed the language with
its unique needs and backward compatibility in mind. Client-side
ActionScript has also evolved over time. The earlier implementation
supported in Flash MX (and still supported in Flash MX 2004) has been
retroactively dubbed ActionScript 1.0. The latest
implementationsupported in Flash MX 2004 and closer to ECMA compliance
than earlier implementationsis named ActionScript 2.0. For
more information on the differences between Flash ActionScript 1.0
and ECMAScript, see Appendix D in ActionScript for Flash
MX: The Definitive Guide (O'Reilly). For
details on ActionScript 2.0 and how it diverges from the ECMA
standards, see Essential ActionScript 2.0, also
from O'Reilly.
Contrary to client-side ActionScript, Server-Side ActionScript
conforms to the ECMAScript standard because Macromedia used the
Mozilla Spidermonkey JavaScript 1.5 interpreter in FlashCom. More
information on it and JavaScript 1.5 are available here:
- http://www.mozilla.org/js
This section outlines the differences that you should watch out for
between client-side ActionScript and Server-Side ActionScript.
4.2.1. Case-Sensitivity
Server-Side
ActionScript is always case-sensitive, while
client-side
ActionScript may not be. In Flash 5 and Flash MX, most ActionScript
is not case-sensitive. For example, in Flash MX,
myVariable and MyVariable refer
to the same variable. In server-side scripts, they do not.
Many developers continue to be confused by the case-sensitivity rules
in Flash MX 2004, which depend in part on the version (SWF format)
and ActionScript version (compiler version) chosen under
File Publish
Settings Flash. Realize
first that we are talking about two different issues for client-side
ActionScript: compile-time case-sensitivity and runtime
case-sensitivity. The ActionScript 1.0 compiler is not
case-sensitive, whereas the ActionScript 2.0 compiler is. However,
runtime case-sensitivity is a function of the version of the SWF
format to which you export, not the ActionScript
version used at compile time nor the version of the Flash Player
plugin in which the file is played.
Runtime case-sensitivity is summarized in Table 4-1, reproduced from Colin
Moock's Essential ActionScript
2.0. Note that ActionScript 1.0 and 2.0 are both
case-sensitive when exported in Flash Player 7-format
.swf files and played in Flash Player 7. In
other runtime cases, code is case-insensitive subject to the
exceptions cited in the footnotes to
the table.
Table 4-1. Runtime case-sensitivity support by language, file format, and Flash Player version|
Movie compiled as either ActionScript 1.0 or 2.0 and
|
Played in Flash Player 6
|
Played in Flash Player 7
|
|---|
|
Flash Player 6-format .swf file
|
Case-insensitivea
|
Case-insensitivea
| |
Flash Player 7-format .swf file
|
Not supportedb
|
Case-sensitive
|
aIdentifiers (i.e., variable and property names), function names,
frame labels, and symbols export IDs are case-insensitive in Flash
Player 6-format .swf files. But reserved words
such as if are case-sensitive, even in Flash
Player 6.
bFlash Player 6 cannot play Flash Player 7-format .swf
files.
 |
Regardless of whether you are writing client-side ActionScript or
SSAS, we strongly recommend maintaining consistent usage of upper-
and lowercase in all your code to avoid problems.
|
|
If you are careful to always capitalize names in the same way and
never use capitalization to distinguish between variable names or
other identifiers, you shouldn't have any problems.
However, in JavaScript it is a common practice to use capitalization
to distinguish between the name of a constructor function and an
instance of a class, as follows:
function User ( ) {
}
// The user variable holds an instance of the User class
user = new User( );
In Flash 5 and Flash MX, this would essentially disable the
constructor, but in SSAS, the difference in capitalization means that
User (the class) and user (a
variable holding an instance of the class) are different entities. A
common practice to avoid confusion is to append the word
"Class" onto the constructor
function name:
function UserClass ( ) {
}
user = new UserClass( );
4.2.2. Working with Inheritance
Server-Side
ActionScript does not support the formal definition of classes and
interfaces supported by client-side ActionScript 2.0. SSAS supports
prototype-based inheritance but is a little different from Flash
ActionScript 1.0. Flash MX added the super
operator to client-side ActionScript to make it easy to call the
constructor function and methods of a superclass. Although
super is not part of the ECMAScript version 3
language defined in ECMA-262, it is proposed for a future version of
the standard. The super operator is not available in SSAS.
However you can permit a subclass to access the constructor and
methods of a superclass in a number of ways in SSAS. Example 4-1 shows one way to call the constructor and
methods of a
superclass in SSAS.
Example 4-1. Calling the constructor and methods of a superclass in SSAS
SuperClass = function (a) {
this.a = a;
};
SuperClass.prototype.method = function ( ) {
trace("SuperClass method called. a is: " + this.a);
};
SubClass = function (a, b) {
SuperClass.apply(this, arguments);
this.b = b;
};
SubClass.prototype = new SuperClass( );
SubClass.constructor = SubClass;
SubClass.prototype.method = function ( ) {
trace("In Subclass method. a and b: " + this.a + ", " + this.b);
SuperClass.prototype.method.apply(this, arguments);
};
subClass = new SubClass(1, 2);
subClass.method( );
An excellent discussion of object-oriented programming and
prototype-based inheritance using JavaScript is available in
JavaScript: The Definitive Guide, Fourth Edition
(O'Reilly) by David Flanagan.
Flanagan's book is especially useful for server-side
scripting as it covers JavaScript 1.5the exact same language
as SSAS.
Prototype-based inheritance issues
in Flash 5 and Flash MX and the various options for implementing
inheritance without using super in Flash are
discussed in detail here:
- http://www.quantumwave.com/flash/inheritance.html
While the discussion centers around Flash, it is also a valuable
resource for server-side scripting.
Many of the communication objects available cannot be subclassed
using these sorts of techniques. For example, shared objects are not
created by calling a constructor function. Instead, they are created
via a static method such as SharedObject.getRemote(
) on the client or get(
) on the server. Often there are better ways to work with
the communication classes than inheriting from them. See Chapter 15 for more details.
4.2.3. Single Execution Context
Client-side ActionScript provides a
special _global object that provides a place to
store global variables that exist outside the scope of the timeline.
For example:
// Assume a _global object already exists.
_global.x = 3; // OK in client-side AS; however, error in SSAS.
trace (x); // Will output: 3 in Flash MX and later.
In client-side ActionScript, if a variable is not found on the
timeline and the _global object has a property of
the same name, the _global
object's property is accessed.
In SSAS there are no timelines. All server-side code executes in one
global context that is associated with each application instance. So
there is little point to providing a special
_global object. You can create an object named
_global, but it will not work as it does in
client-side ActionScript. In general, you should avoid creating an
object named _global in SSAS because it
doesn't add anything and may create problems if you
are using Flash Remoting (see Chapter 11).
When loaded into a main.asc file, the
netservices.asc file creates a new
_global object and assigns properties to it. The
RecordSet.asc file also adds properties to the
_global object. Furthermore,
netservices.asc adds the unshift(
) and registerClass( ) methods to the
Object class; since all classes inherit from
Object, every object shows these methods when
its properties are enumerated with a for-in
loop. Chapter 11 contains additional information
on dealing with these inconveniences. If you must use a
_global object in SSAS, you should check whether
it already exists before creating your own and be careful to avoid
collisions with the _global properties defined in
netservices.asc.
4.2.4. Accessing Undefined Variables
It is common to see tests for undefined variables in
client-side ActionScript as follows:
if (xyz == undefined) { // Don't do this on the server!
trace("xyz is undefined.");
}
However, the preceding code will throw a reference error on the
server because the variable xyz does not exist. To
get around this, use the typeof operator, as
follows:
if (typeof xyz == "undefined") {
trace("xyz does not exist");
}
Using typeof is not necessary within the body of
a function where the variable is local by virtue of being declared
using var or passed in via the
function's parameter list. The following is okay in
SSAS as well as in client-side ActionScript:
var xyz;
if (xyz == undefined) {
trace("xyz is undefined.");
}
And so is this:
someFunction = function (xyz) {
if (xyz == undefined) {
trace("xyz is undefined.");
}
};
4.2.5. try/catch/finally Statements
If you look through the server-side communication components code in
the scriptlib/components folder, you will see
frequent use of
try/catch statements. For example, the
server-side FCChat component is guaranteed to be defined only once by
placing the definition within a catch block:
try {var dummy = FCChat;} catch (e) { // #ifndef FCChat
// The FCChat class is defined here...
}
The try/catch/finally statement is supported in client-side
ActionScript 2.0, but AS 2.0 does not support runtime type and
reference checking. For details on
try/catch/finally in ActionScript 2.0, see the
chapter on exception handling in Essential ActionScript
2.0. For a description of how to use
try, catch,
finally, throw, and
Error objects in JavaScript (which also applies
to SSAS), see JavaScript: The Definitive Guide, Fourth
Edition.
Using try/catch statements has the advantage
that errors, including type and reference errors, that would
otherwise stop the execution of server-side scripts can be caught and
handled. We've already seen an example of a
reference error (an error caused by trying to refer to a non-existent
variable). A type error occurs if you attempt to access the property
of an undefined or null object. The following short SSAS script
causes execution to stop when a type error occurs. If you run it
using the App Inspector (a testing utility introduced in
"Admin Service, Administration Console, and App
Inspector" in Chapter 1 and
used later under "Testing and Debugging Server-Side
Script Files"), you will see the error message
"status has no properties" and the
last trace( ) statement will never be executed:
status = null;
trace(status.property); // Causes a type error
trace("Unreachable trace statement.");
On the other hand, wrapping the same code in a
try block makes it possible to recover from the
error:
try {
status = null;
trace(status.property);
trace("Unreachable trace statement.");
}
catch (e) {
trace("Error name and message: " + e.name + ", " + e.message);
}
finally {
trace("No matter what,this statement will be executed.");
}
trace("Processing can continue here...");
If this simple script is run in the App Inspector, the following
output appears:
Error name and message: TypeError, status has no properties
No matter what, this statement will be executed.
Processing can continue here...
While ActionScript 2.0 does have a
try/catch/finally statement, it does not support
runtime type or reference checking. The same script run in Flash MX
2004 produces the following output, because
TRace(status.property); outputs
"undefined" instead of throwing an
error:
undefined
Unreachable trace statement.
No matter what, this statement will be executed.
4.2.6. #include and import Versus load( )
Server-Side ActionScript uses the
load( ) function in place of the
#include directive (common in client-side
ActionScript 1.0) to load other ActionScript source files into
another script. The load( ) method is described
under "Using load( ) to Include Other Script
Files" later in this chapter. The
import statement is not supported in SSAS,
and there is no concept of class files organized into packages as
there are in ActionScript 2.0. Again, see Essential
ActionScript 2.0 for a full discussion of client-side
ActionScript classes and packages.
 |