2012/9/24

在 jQuery 自訂函式中實作 Optional Parameters

jQuery 的自訂函式事實上就是 jQuery 的外掛 (Plugin), 宣告的方式很簡單, 如下範例所示:

jQuery.f2c = function(fahrenheit) 
{ 
 return (fahrenheit-32) * 5/9; 
}

如此, 我們就建立了一個名字叫做 f2c 的外掛, 而且馬上就可以使用 $.f2c 予以呼叫:

document.write($.f2c(32));
document.write("<br/>");
document.write($.f2c(212));

如果你想建立一個可以作用於某個 jQuery 物件的自訂函式, 那麼寫法略有不同。你可以參考「jQuery 外掛開發風格及其重要性」這篇文章。由於它寫得非常清楚, 細節的部份我就不再引述。

可省略的參數

本文的重點, 將著重在如何實作 Optional Parameters, 也就是說, 要如何模仿 C# 或 VB 中的可省略參數值。

其實, 僅需使用 JavaScript 的內建功能, 這個需求可以很輕鬆容易地辦到。在上例中, 我們只需改寫如下即可:

jQuery.f2c = function(fahrenheit) 
{
 if (!fahrenheit) fahrenheit = 32;
 return (fahrenheit-32) * 5/9; 
}

如此, 如果呼叫 f2c() 函式且不帶任何參數的話, 該參數的預設值就是 32。

在我舉的這個例子中, 這種寫法應該是最直覺的寫法。然而, 在其它情境中, 如果參數很多 (例如十幾個) 的話, 這種寫法就變得非常不切實際了!

在這種情況下, 我們必須採取另一種比較迂迴, 但是彈性更大的做法。

不過, 在繼續進行之前, 我們必須先來看看 jQuery 中的 extend 函式。

根據文件, jQuery.extend() 函式的目的是把兩個以上的物件合併到第一個物件。其語法如下:

jQuery.extend([deep], target, object1 [, objectN])

其中的 deep 應賦予 true/false 值, 如果為真, 將進行 deep copy, 亦即使用遞迴方式進行合併。

target 則是將被合併的物件, 也是傳回值。object1 ~ objectN 則是其它將被合併的物件。

由於這個函式被命名為 extend, 為了避免讀者把它拿來與其它物件導向語言中的 "extend" 特性產生聯想, 所以特別把它解釋了一下。

承襲上面的範例, 我要為 f2c 這個函式建立一個預設值物件:

jQuery.f2c.default = 
{
 fahrenheit: 32
};

fahrenheit 參數的預設值 (在本例中設定為 32) 在這裡定義。

接著, 由於需要用到的變數多了兩個, 所以我必須把 f2c 函式改寫一下。我建立了一個新的變數 opts, 它的值將是 jQuery.f2c.default 與原來的輸入參數 option (即未修改前的 fahrenheit 變數) 的合併:

jQuery.f2c = function(option)
{
    var opts = jQuery.extend(
        {},
        jQuery.f2c.default, 
        option);
    return (opts.fahrenheit-32) * 5/9;
};

各位可以注意到, 在原始程式中輸入參數 fahrenheit 預期的是一個原始型別 (float), 改寫之後, 參數 option 預期為一個 jQuery 物件, 所以你不能再傳入 float 型別。換句話說, 如果執行 $.f2c(32) 的話, 程式會發生錯誤。

在這裡, 我把第一個參數設定為 {} (空物件) 而非 jQuery.f2c.default, 是為了避免 jQuery.f2c.default 的值被覆蓋 (因為以後可能還會用到); 如果「預設值」可以被動態覆蓋的話, 它也不叫做「預設值」了, 對吧? 這個空物件在 extend() 函式被執行之後, 會被填入 jQuery.f2c.default 和 option 兩個物件的合併值並被傳回。由於 jQuery 物件都是全域物件, 所以我們要特別留意這種寫法的必要性, 以免遺留難以追蹤的 bug。

經過修改之後, 我們就可以省去 f2c 的參數了 (會自動以 32 這個預設值取代)。

如果要賦予 32 以外的值, 我們可以帶入指定的值, 使用 $.f2c({fahrenheit: 212}) 的方式。

Live Demo

以下是完整而可執行的程式碼:

你可以在 jsFiddle 上進行練習或改寫上述程式。

沒有留言:

張貼留言