调用函数
可通过使用后跟小括号运算符 (
()
) 的函数标识符来调用函数。要发送给函数的任何函数参数都括在小括号中。例如,
trace()
函数在 ActionScript 3.0 中是一个顶级函数:
trace("Use trace to help debug your script");
如果要调用没有参数的函数,则必须使用一对空的小括号。例如,可以使用没有参数的
Math.random()
方法来生成一个随机数:
var randomNum:Number = Math.random();
函数语句
函数语句是在严格模式下定义函数的首选方法。函数语句以
function
关键字开头,后跟:
例如,下面的代码创建一个定义一个参数的函数,然后将字符串“
hello
”用作参数值来调用该函数:
function traceParameter(aParam:String)
{
trace(aParam);
}
traceParameter("hello"); // hello
在函数语句和函数表达式之间进行选择
原则上,除非在特殊情况下要求使用表达式,否则应使用函数语句。函数语句较为简洁,而且与函数表达式相比,更有助于保持严格模式和标准模式的一致性。
函数语句比包含函数表达式的赋值语句更便于阅读。与函数表达式相比,函数语句使代码更为简洁而且不容易造成混淆,因为函数表达式既需要
var
关键字又需要
function
关键字。
函数语句更有助于保持严格模式和标准模式的一致性,因为在这两种编译器模式下,均可借助点语法来调用使用函数语句声明的方法。但这对于用函数表达式声明的方法却不一定成立。例如,下面的代码定义了一个具有下面两个方法的 Example 类:
methodExpression()
(用函数表达式声明)和
methodStatement()
(用函数语句声明)。在严格模式下,不能使用点语法来调用
methodExpression()
方法。
class Example
{
var methodExpression = function() {}
function methodStatement() {}
}
var myEx:Example = new Example();
myEx.methodExpression(); // error in strict mode; okay in standard mode
myEx.methodStatement(); // okay in strict and standard modes
一般认为,函数表达式更适合于关注运行时行为或动态行为的编程。如果您喜欢使用严格模式,但是还需要调用使用函数表达式声明的方法,则可以使用这两种方法中的任一方法。首先,可以使用中括号 (
[]
) 代替点运算符 (
.
) 来调用该方法。下面的方法调用在严格模式和标准模式下都能够成功执行:
myExample["methodLiteral"]();
第二,您可以将整个类声明为动态类。尽管这样您就可以使用点运算符来调用方法,但缺点是,该类的所有实例在严格模式下都将丢失一些功能。例如,如果您尝试访问动态类实例的未定义属性,则编译器不生成错误。
在某些情况下,函数表达式非常有用。函数表达式的一个常见用法就是用于那些使用一次后便丢弃的函数。另一个用法就是向原型属性附加函数,这个用法不太常见。有关详细信息,请参阅原型对象。
函数语句与函数表达式之间有两个细微的区别,在选择要使用的方法时,应考虑这两个区别。第一个区别体现在内存管理和垃圾回收方面,因为函数表达式不像对象那样独立存在。换言之,当您将某个函数表达式分配给另一个对象(如数组元素或对象属性)时,就会在代码中创建对该函数表达式的唯一引用。如果该函数表达式所附加到的数组或对象脱离作用域或由于其他原因不再可用,您将无法再访问该函数表达式。如果删除该数组或对象,该函数表达式所使用的内存就会符合垃圾回收条件,这意味着内存符合回收条件并可重新用于其他用途。
下面的示例说明对于函数表达式,一旦删除该表达式所赋予的属性,该函数就不再可用。Test 类是动态的,这意味着您可以添加一个名为
functionExp
的属性来保存函数表达式。
functionExp()
函数可以用点运算符来调用,但是一旦删除了
functionExp
属性,就无法再访问该函数。
dynamic class Test {}
var myTest:Test = new Test();
// function expression
myTest.functionExp = function () { trace("Function expression") };
myTest.functionExp(); // Function expression
delete myTest.functionExp;
myTest.functionExp(); // error
另一方面,如果该函数最初是用函数语句定义的,那么,该函数将以对象的形式独立存在,即使在您删除它所附加到的属性之后,该函数仍将存在。
delete
运算符仅适用于对象的属性,因此,即使是用于删除
stateFunc()
函数本身的调用也不工作。
dynamic class Test {}
var myTest:Test = new Test();
// function statement
function stateFunc() { trace("Function statement") }
myTest.statement = stateFunc;
myTest.statement(); // Function statement
delete myTest.statement;
delete stateFunc; // no effect
stateFunc();// Function statement
myTest.statement(); // error
函数语句与函数表达式之间的第二个区别是,函数语句存在于定义它们的整个作用域(包括出现在该函数语句前面的语句)内。与之相反,函数表达式只是为后续的语句定义的。例如,下面的代码能够在定义
scopeTest()
函数之前成功调用该函数:
statementTest(); // statementTest
function statementTest():void
{
trace("statementTest");
}
函数表达式只有在定义之后才可用,因此,下面的代码会生成运行时错误:
expressionTest(); // run-time error
var expressionTest:Function = function ()
{
trace("expressionTest");
}
从函数中返回值
要从函数中返回值,请使用后跟要返回的表达式或字面值的
return
语句。例如,下面的代码返回一个表示参数的表达式:
function doubleNum(baseNum:int):int
{
return (baseNum * 2);
}
请注意,
return
语句会终止该函数,因此,不会执行位于
return
语句下面的任何语句,如下所示:
function doubleNum(baseNum:int):int {
return (baseNum * 2);
trace("after return"); // This trace statement will not be executed.
}
在严格模式下,如果您选择指定返回类型,则必须返回相应类型的值。例如,下面的代码在严格模式下会生成错误,因为它们不返回有效值:
function doubleNum(baseNum:int):int
{
trace("after return");
}
嵌套函数
您可以嵌套函数,这意味着函数可以在其他函数内部声明。除非将对嵌套函数的引用传递给外部代码,否则嵌套函数将仅在其父函数内可用。例如,下面的代码在
getNameAndVersion()
函数内部声明两个嵌套函数:
function getNameAndVersion():String
{
function getVersion():String
{
return "10";
}
function getProductName():String
{
return "Flash Player";
}
return (getProductName() + " " + getVersion());
}
trace(getNameAndVersion()); // Flash Player 10
在将嵌套函数传递给外部代码时,它们将作为函数闭包传递,这意味着嵌套函数保留在定义该函数时处于作用域内的任何定义。有关详细信息,请参阅函数作用域。