對於要重複執行的內容,你可以定義函式。例如:
js> function max(num1, num2) {
> return num1 > num2 ? num1 : num2;
> }
js> max(10, 5);
10
js>
> 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>
> 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>
> 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>
> 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>
> 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>
> 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>
> 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>
在上例中,呼叫函式時必須提供物件,物件上帶有函式所需的資料,函式內部對於物件上沒有提供資料時,會提供預設值。