Flash CS3 文件 |
|||
| ActionScript 3.0 程式設計 > ActionScript 語言和語法 > 函數 > 基本的函數觀念 | |||
本節將探討基本的函數定義和叫用技巧。
您必須使用函數的識別名稱,後面跟著括號運算子 (()) 來呼叫函數。您必須使用括號運算子,括住要傳送給該函數的任何函數參數。例如,trace() 函數是 Flash Player API 中的最高階函數,在本書中從頭到尾都會用到:
trace("Use trace to help debug your script");
若要在不使用參數的情況下呼叫函數,則必須使用一對空的括號。例如,您可以使用 Math.random() 方法產生隨機數字,此方法不會使用任何參數:
var randomNum:Number = Math.random();
在 ActionScript 3.0 中有兩種方式可以定義函數。您可以使用函數陳述式,或是使用函數運算式。您所選擇的技巧會根據偏好較靜態或較動態的程式設計方式而定。若您偏好靜態或嚴謹模式的程式設計方式,則可以用函數陳述式定義函數;若有特別需求,則可以用函數運算定義函數,函數運算式比較常用在動態或標準模式的程式設計中。
在嚴謹模式中,較為偏好使用函數陳述式來定義函數。函數陳述式是以 function 關鍵字做為開頭,後面再加上:
例如,下列程式碼會建立定義參數的函數,然後用 "hello" 字串做為參數值,叫用該函數。
function traceParameter(aParam:String)
{
trace(aParam);
}
traceParameter("hello"); // hello
宣告函數的第二種方式是,使用具有函數運算式的指定陳述式,而函數運算式有時又稱為函數常值或匿名函數。這是比較詳細而冗長的方法,在舊版 ActionScript 中廣泛地使用。
具有函數運算式的指定陳述式是以 var 關鍵字做為開頭,後面再加上:
:)Function 類別,以指出資料類型=)function 關鍵字例如,下列程式碼會使用函數運算式,宣告 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");
一般原則是,除非有特定情況需要使用運算式,否則就使用函數陳述式。函數陳述式不那麼詳細而冗長,而且在嚴謹模式與標準模式之間,提供比函數運算式更一致的體驗。
函數陳述式比包含函數運算式的指定陳述式更容易閱讀。函數陳述式可以讓您的程式碼更簡潔,也沒有函數運算式那麼困惑難解,因為函數運算式需要同時使用 var 和 function 兩個關鍵字。
函數陳述式之所以能在兩個編譯器模式之間提供更一致的體驗,在於您可以同時在嚴謹模式與標準模式使用點語法,叫用使用函數陳述式宣告的方法;而用函數運算式宣告的方法就不一定能夠這樣。例如,下列程式碼會定義名為 Example 的類別,此類別具有兩個方法:用函數運算式宣告的 methodExpression() 以及用函數陳述式宣告的 methodStatement()。在嚴謹模式中,您不能使用點語法叫用 methodExpression() 方法。
class Example
{
var methodExpression = function() {}
function methodStatement() {}
}
var myEx:Example = new Example();
myEx.methodExpression(); // 嚴謹模式中發生錯誤;但標準模式沒有問題
myEx.methodStatement(); // 嚴謹模式與標準模式都沒有問題
一般都認為,函數運算式更適合用來進行著重執行階段或動態行為方式的程式設計。若偏好使用嚴謹模式,但也需要呼叫用函數運算式宣告的方法,您可以使用兩種技巧其中任一種。首先,您可以使用方括號 ([]) 而不使用點 (.) 運算子,呼叫方法。下列方法呼叫在嚴謹模式和標準模式中都會成功:
myExample["methodLiteral"]();
第二,您可以將整個類別宣告為動態類別。雖然這樣可以讓您使用點運算子呼叫方法,不過缺點是犧牲了在嚴謹模式中該類別所有實體的一些功能。例如,如果嘗試在動態類別的實體上存取未定義的屬性,編譯器不會產生錯誤。
在一些情況下,函數運算式很有用。函數運算式的一個常用用法是,供只用一次就捨棄的函數使用;另外,較不常用的用法則是用來將函數附加至原型屬性。如需詳細資訊,請參閱原型 (Prototype) 物件。
在函數陳述式與函數運算式之間有兩個微小的差異,您應該在選擇所要使用的技巧時將其納入考量。第一項差異是,在記憶體管理和記憶體回收方面,函數運算式不會做為物件獨立存在。換句話說,當您將函數運算式指定至另一個物件,例如陣列元素或物件屬性,只是在程式碼中建立該函數運算式的參考。若函數運算式所附加的陣列或物件超出範圍之外,或是因其它原因無法再使用,您將無法再存取該函數運算式。若刪除該陣列或物件,函數運算式所使用的記憶體將可供進行記憶體回收,也就是說,該記憶體可開始回收,重新做為其它用途。
下列範例會示範,就函數運算式而言,一旦刪除了運算式所指定的屬性,就不能再使用該函數。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
function statementTest():void
{
trace("statementTest");
}
函數運算式在定義之前無法使用,因此下列程式碼就會產生執行階段錯誤:
expressionTest(); // 執行階段錯誤
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"); // 這個 trace 陳述式將不會執行。
}
在嚴謹模式中,若選擇指定傳回類型,則必須傳回適當類型的值。例如,下列程式碼會在嚴謹模式中產生錯誤,因為它不會傳回有效值:
function doubleNum(baseNum:int):int
{
trace("after return");
}
您可以讓函數形成巢狀結構,也就是說,可以在其它函數之內宣告函數。除非將巢狀函數參考傳遞至外部程式碼,否則一個巢狀函數只能在其父函數內使用。例如,下列程式碼會在 getNameAndVersion() 函數內宣告兩個巢狀函數:
function getNameAndVersion():String
{
function getVersion():String
{
return "9";
}
function getProductName():String
{
return "Flash Player";
}
return (getProductName() + " " + getVersion());
}
trace(getNameAndVersion()); // Flash Player 9
當巢狀函數傳遞至外部程式碼時,是做為函數結束項傳遞,也就是說,函數會保留定義函數時在範圍內的任何定義。如需詳細資訊,請參閱函數結束項。
Flash CS3
目前頁面: http://livedocs.adobe.com/flash/9.0_tw/main/00000054.html