函式宣告



對於要重複執行的內容,你可以定義函式。例如:
js> function max(num1, num2) {
  >     return num1 > num2 ? num1 : num2;
  > }
js> max(10, 5);
10
js>


在上面的例子示範了函式的基本宣告與呼叫方式。函式使用function宣告名稱,參數位於括號之中,使用return傳回執行結果,如果沒有宣告return傳回任何結果,預設傳回undefined

在函式上的參數宣告,只是傳入引數的具名參考,實際上,宣告函式時若傳入的引數少於參數是可行的,不足的部份,參數就是undefined
js> function func(a, b) {
  >     print(a);
  >     print(b);
  > }
js> func(10, 20);
10
20
js> func(10);
10
undefined
js> func();
undefined
undefined
js> func(10, 20, 30, 40);
10
20
js>


在上例中,你也看到了,就算傳入比參數個數還多的引數也是可行的,那多的引數跑到哪去了?事實上,在函式內部會自動宣告arguments名稱參考至具陣列外觀的物件,上頭帶有所有傳入的引數。例如,你可以如下設計一個加總數值的函式:
js> function sum() {
  >     var sum = 0;
  >     for(var i = 0; i < arguments.length; i++) {
  >         sum += arguments[i];
  >     }
  >     return sum;
  > }
js> sum(1, 2);
3
js> sum(1, 2, 3);
6
js> sum(1, 2, 3, 4);
10
js>


arguments不是Array實例,它只是具有數字作為特性,特性參考至傳入的引數,並具有length特性代表傳入引數的個數

在JavaScript中,參數只是具名的引數,事實上,你改變參數的值,arguments對應索引的參考值也會相應的改變:
js> function func(a, b) {
  >     print(a + ': ' + arguments[0]);
  >     print(b + ': ' + arguments[1]);
  >     a = 0;
  >     b = 0;
  >     print(a + ': ' + arguments[0]);
  >     print(b + ': ' + arguments[1]);
  > }
js> func(100, 200);
100: 100
200: 200
0: 0
0: 0
js>


由於呼叫函式時傳入的引數個數不一定要等於參數個數,因此若要確認引數等於參數個數,可透過arguments的length來檢查傳入的引數個數。例如:
js> function func(a, b) {
  >     if(arguments.length != 2) {
  >         throw new Error('must give 2 arguments');
  >     }
  > }
js> func(10);

js: "<stdin>", line 40: exception from uncaught JavaScript throw: Error: must give 2 arguments
        at <stdin>:40 (func)
        at <stdin>:39

js> func(10, 20);
js>


事實上,在JavaScript程式設計上的慣例,很少檢查引數個數,而是在引數不足時提供預設值,這很容易辦到,因為引數不足時,不足的參數會是undefined,而undefined在判斷式中會被當false,所以可以撰寫如下來提供預設值:
js> function numberGenerator(length, begin, step) {
  >     begin = begin || 0;
  >     step = step || 1;
  >     var numbers = [begin];
  >     length--;
  >     for(var i = 0; i < length; i++) {
  >         numbers.push(numbers[i] + step);
  >     }
  >     return numbers;
  > }
js> numberGenerator(10);
0,1,2,3,4,5,6,7,8,9
js> numberGenerator(10, 5);
5,6,7,8,9,10,11,12,13,14
js> numberGenerator(10, 5, 2);
5,7,9,11,13,15,17,19,21,23
js>


在上例是一個數值產生器,length一定要提供,若不提供begin的話,預設起始值就是0,若不提供step的話,步進值就是1。

如果在選項非常多時,還會採用選項物件(Option object)的方式。例如:
js> function func(option) {
  >     option = {
  >         x : option.x || 10,
  >         y : option.y || 20,
  >         z : option.z || 30
  >     };
  >     print(option.x);
  >     print(option.y);
  >     print(option.z);
  > }

js> func({ x : 100 });
100
20
30
js> func({ x : 100, y : 200 });
100
200
30
js> func({ x : 100, y : 200, z : 300 });
100
200
300
js>


在上例中,呼叫函式時必須提供物件,物件上帶有函式所需的資料,函式內部對於物件上沒有提供資料時,會提供預設值。