函數參數

ActionScript 3.0 提供函數參數一些功能,對剛開始使用此語言的程式設計人員會顯得很新奇。雖然以傳值或以傳址方式傳遞參數的概念對大部分程式設計人員來說應該很熟悉,但是 arguments 物件及 ...(rest) 參數可能對很多人來說都是新觀念。

副主題

以傳值或以傳址方式來傳遞引數
預設參數值
arguments 物件
...(rest) 參數

以傳值或以傳址方式來傳遞引數

在許多程式設計語言中,瞭解以傳值或以傳址方式傳遞引數之間的區別是很重要的,這項區別可能會影響程式碼設計的方式。

以傳值方式來傳遞表示:引數的值是拷貝到區域變數內,以便在函數中使用。以傳址方式來傳遞表示:只傳遞了引數的參考,而沒有傳遞實際的值;沒有製作實際引數的副本,而是建立了傳遞做為引數的變數參考,並指定給區域變數,以便在函數中使用。區域變數是函數之外的變數參考,讓您能夠變更原始的變數值。

在 ActionScript 3.0 中,所有引數都是以傳址方式傳遞,因為所有的值都會儲存為物件。但是屬於基本資料類型的物件 (包括 Boolean、Number、int、uint 和 String) 都有特殊運算子,使它們能夠表現得像是以傳值方式傳遞。例如,下列程式碼會建立名為 passPrimitives() 的函數,以定義兩個同樣是 int 類型的參數:xParamyParam。這些參數類似於在 passPrimitives() 函數主體內部宣告的區域變數。當函數是以引數 xValueyValue 呼叫時,參數 xParamyParam 都是用以 xValueyValue 代表的 int 物件參考進行初始化。因為引數是基本型,所以表現得就像是以傳值方式傳遞一樣。雖然 xParamyParam 最初只包含 xValueyValue 物件的參考,但是在函數主體之內的任何變數變更都會在記憶體中產生新的值副本。

function passPrimitives(xParam:int, yParam:int):void
{
    xParam++;
    yParam++;
    trace(xParam, yParam);
}

var xValue:int = 10;
var yValue:int = 15;
trace(xValue, yValue);          // 10 15
passPrimitives(xValue, yValue); // 11 16
trace(xValue, yValue);          // 10 15

passPrimitives() 函數內,xParamyParam 的值是遞增的,但這並不會影響 xValueyValue 的值,如上一個 trace 陳述式所示。即使參數名稱與變數名稱 xValueyValue 完全相同也是如此,因為函數之內的 xValueyValue 會指向記憶體中的新位置,與函數之外名稱相同的變數不同。

所有其它物件 (也就是不屬於基本資料類型的物件) 都是依傳址方式傳遞,讓您能夠改變原始變數的值。例如,下列程式碼會建立名為 objVar 的物件,具有 xy 兩個屬性。物件是以引數形式傳遞給 passByRef() 函數。因為該物件不是基本類型,所以該物件不但是以傳址方式傳遞,而且一直保持為參考。這表示,在函數內對參數所做的變更將影響函數外的物件屬性。

function passByRef(objParam:Object):void
{
    objParam.x++;
    objParam.y++;
    trace(objParam.x, objParam.y);
}
var objVar:Object = {x:10, y:15};
trace(objVar.x, objVar.y); // 10 15
passByRef(objVar);         // 11 16
trace(objVar.x, objVar.y); // 11 16

objParam 參數會參考全域 objVar 變數所參考的相同物件。如範例中的 trace 陳述式所示,對 objParam 物件之 xy 屬性所做的變更已反映在 objVar 物件中。

預設參數值

ActionScript 3.0 中有一項新增的功能,就是宣告函數的「預設參數值」。若呼叫有預設參數值的函數省略了有預設值的參數,就使用該參數在函數定義中指定的值。所有具預設值的參數都必須放在參數清單最後。指定做為預設值的值必須是編譯階段常數。參數有預設值存在可以有效地讓參數成為「選擇性的參數」。沒有預設值的參數即視為「必要參數」。

例如,下列程式碼會建立具有三個參數的函數,其中有兩個有預設值。當函數只用一個參數呼叫時,就使用參數的預設值。

function defaultValues(x:int, y:int = 3, z:int = 5):void
{
    trace(x, y, z);
}
defaultValues(1); // 1 3 5

arguments 物件

當參數傳遞給函數時,您可以使用 arguments 物件,存取有關傳遞函數之參數的資訊。arguments 物件具有下列重要的方面:

注意

 

arguments 物件無法使用的情形如下:如果有任何參數命名為 arguments,或是如果使用 ...(rest) 參數。

ActionScript 3.0 允許函數呼叫包含比函數定義中所定義更多的參數,但若參數的數目少於必要參數的數目,就會在嚴謹模式中產生編譯器錯誤。您可以使用 arguments 物件的陣列方面,存取傳遞給函數的任何參數,不管該參數是否定義於函數定義中。下列範例會使用 arguments 陣列與 arguments.length 屬性,以追蹤傳遞給 traceArgArray() 函數的所有參數:

function traceArgArray(x:int):void
{
    for (var i:uint = 0; i < arguments.length; i++)
    {
        trace(arguments[i]);
    }
}

traceArgArray(1, 2, 3);

// 輸出:
// 1
// 2
// 3

arguments.callee 屬性經常用於匿名函數中,以建立遞迴。您可以用它來增加程式碼的彈性。如果您在開發週期的過程中變更了遞迴函數的名稱,若使用 arguments.callee 而不用函數名稱,就不需要擔心函數主體中遞迴呼叫的變更。arguments.callee 屬性是在下列函數運算式中使用,以啟用遞迴:

var factorial:Function = function (x:uint)
{
    if(x == 0)
    {
        return 1;
    }
    else
    {
        return (x * arguments.callee(x - 1));
    }
}

trace(factorial(5)); // 120

如果在函數宣告中使用 ...(rest) 參數,您就無法使用 arguments 物件,而必須使用為它們宣告的參數名稱來存取參數。

您也應該小心避免使用字串 "arguments" 做為參數名稱,因為它會遮蔽 arguments 物件。例如,若重新撰寫 traceArgArray() 函數以加入 arguments 參數,則函數主體中的 arguments 參考的是參數,而不是 arguments 物件。下列程式碼不會產生輸出:

function traceArgArray(x:int, arguments:int):void
{
    for (var i:uint = 0; i < arguments.length; i++)
    {
        trace(arguments[i]);
    }
}

traceArgArray(1, 2, 3);

// 無輸出

在舊版 ActionScript 中,arguments 物件也包含名為 caller 的屬性,它是參考呼叫目前函數的函數;在 ActionScript 3.0 中則沒有caller 屬性,但是如果您需要參考呼叫函數,可以改變呼叫函數,以便傳遞參考它本身的額外參數。

...(rest) 參數

ActionScript 3.0 中加入了新的參數宣告,稱為 ...(rest) 參數。此參數可以讓您指定接受任何以逗號分隔引數數目的陣列參數。該參數可以包含任何不是保留字的名稱。此參數宣告必須是最後指定的參數。使用此參數會使 arguments 物件無法使用。雖然 ...(rest) 參數可提供您等同 arguments 陣列與 arguments.length 屬性的功能,但卻無法提供類似 arguments.callee 所提供的功能。您應該先確認不需要使用 arguments.callee 之後,再使用 ...(rest) 參數。

下列範例會重新撰寫 traceArgArray() 函數,並且使用的是 ...(rest) 參數而不是 arguments 物件:

function traceArgArray(... args):void
{
    for (var i:uint = 0; i < args.length; i++)
    {
        trace(args[i]);
    }
}

traceArgArray(1, 2, 3);

// 輸出:
// 1
// 2
// 3

...(rest) 參數也可以與其它參數一併使用,只要是列出的最後一個參數即可。下列範例會修改 traceArgArray() 函數,讓它的第一個參數 x 為 int 類型,而第二個參數再使用 ...(rest) 參數。輸出會略過第一個值,因為第一個參數不再是由 ...(rest) 參數所建立之陣列的一部分。

function traceArgArray(x: int, ... args)
{
    for (var i:uint = 0; i < args.length; i++)
    {
        trace(args[i]);
    }
}

traceArgArray(1, 2, 3);

// 輸出:
// 2
// 3

Flash CS3

 

有新的意見加入至這個頁面時,傳送電子郵件給我 | 意見報告

目前頁面: http://livedocs.adobe.com/flash/9.0_tw/main/00000055.html