呼叫函數
呼叫函數時,必須使用函數的識別名稱,後面跟著括號運算子 (
()
)。括號運算子必須括住要傳送給該函數的任何函數參數。例如,
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
當巢狀函數傳遞至外部程式碼時,會做為函數結束項傳遞,也就是說,函數會保留定義函數時在範圍內的任何定義。如需詳細資訊,請參閱函數範圍。