「函數」(Functions)是所有的程式語言必備的功能。JavaScript 的函數可以分成下列幾類:
內建函數:又分成兩類
一般內建函數,如 parseInt() 和 parseFloat() 等。
與物件結合的函數,例如 Math.sin() 或 string.big()等,這類的函數又稱為物件的方法(Method)。
使用者定義的函數:也可以分一般函數與物件的方法兩類。
本小節將針對使用者定義的函數來進行說明。
Hint 一般而言,我們使用「函數」來代表數學函數,例如三角函數等,而用「函式」來代表程式碼中的函數。但在本書中,並沒有此嚴謹的區分,因此「函式」和「函數」是可以交換使用,通常都是指程式碼所定義的函數。
函數的定義包含函數名稱 (Function name) 及輸入引數 (Input arguments),其基本格式如下:
function functionName(InputArguments) {
JavaScript statements...
...
return(output) // 可省略
}
重點說明如下:
在括號裡的輸入引數(Input Arguments),必須以逗號分開。
定義函數並不代表函數的執行,只有在程式中呼叫函數的名稱後,才會執行該函數。
若有需要,函數最後可用 return 來傳回輸出變數(數值、字串,或其他型態的變數)至呼叫此函數的程式環境。
一般網頁中的的事件處理器(Event handlers),通常都是以 JavaScript 或是 VBScript 的函數來描述。
函數的定義,通常寫在 <head> 及 </head> 之間,甚至也可以寫在網頁最前面(在 <html> 之前),以確保 HTML 主體在被呈現前,所有相關的 JavaScript 函數都已被載入,並隨時可被執行,但這並不是一個嚴格的規定。
一般來說,我們希望函數的定義出現的位置和它被呼叫之處能越接近越好,以方便程式管理,在這種情況下,只要函數定義出現在其被呼叫之前,大致上都不會有什麼問題。
在以下範例中,我們使用兩個函數來顯示現在時間與星期幾:
Example(timeDisplay01.htm ):
此範例原始碼如下:
原始檔(timeDisplay01.htm ): (灰色區域按兩下即可拷貝) <html>
<head>
<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=big5">
</head>
<body>
<h2 align=center>使用函數來顯示現在時間與星期幾</h2>
<hr>
<script>
function currentTime(){ // 回傳現在的時間
var today = new Date();
var hour = today.getHours();
var minute = today.getMinutes();
var second = today.getSeconds();
var prepand = (hour>12)? "下午":"上午";
hour = (hour>12)? hour-12:hour;
return(prepand + hour + " 點 " + minute + " 分 " + second + " 秒");
}
function currentDay(){ // 回傳今天星期幾
var today = new Date();
var day = today.getDay(); // 取得今天是星期幾
var conversion=["天", "一", "二", "三", "四", "五", "六"];
return("星期"+conversion[day]);
}
</script>
<script>
document.write('今天是' + currentDay() + ',目前時間是' + currentTime()+ '!');
</script>
<hr>
</body>
</html>
在使用函數時,我們必須有「局部變數」和「全域變數」的概念,可簡單定義如下:
局部變數 (Local variables):
只有在變數本身的函數裡才看得見的變數。欲定義局部變數,可在變數第一次使用時,加上 var。
全域變數 (Global variables): 在整個程式設計的過程中都可以看得見、
而且每一個函數都可以用的變數。若不對變數做任何處理,JavaScript 的變數預設狀態即是全域變數。
一般而言,如果我們用的變數只在一個函數的有效範圍(Scope)內運作,則此變數通常就應該被設定為局部變數,以免在函數執行後產生副作用,影響到其後程式碼的執行。例如:
Example(scopeOfVariable01.htm ):
此範例的完整原始檔案如下:
原始檔(scopeOfVariable01.htm ): (灰色區域按兩下即可拷貝) <html>
<head>
<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=big5">
</head>
<body>
<h2 align=center>變數的有效範圍</h2>
<hr>
<script>
function testScope() {
var x=5; // 局部變數
y=5; // 全域變數
document.write("Inside function:<br>");
document.write("x = "+x+"<br>");
document.write("y = "+y+"<br>");
}
</script>
<script>
x = 10; // 全域變數
y = 10; // 全域變數
document.write("Before invoking function:<br>");
document.write("x = "+x+"<br>");
document.write("y = "+y+"<br>");
testScope();
document.write("After invoking function:<br>");
document.write("x = "+x+"<br>");
document.write("y = "+y+"<br>");
</script>
<hr>
</body>
</html>
在上述範例中,x 和 y 都是定義為全域變數,但是在函數 testScope() 內,另一個同名的區域變數 x 遮蔽了原先的全域變數 x,因此在函數內印出來的 x 值是 5。但是離開函數之後,x 還是一個全域變數,其值還是 10。變數 y 則是全域變數,因此若在函數中改變其值,也會反映到函數外的 y。
一個常發生的錯誤,就是沒有把函數內部的變數設定成局部變數,導致此變數會繼承或影響外部變數的值。因此,為了減少除錯的時間,所有函數的內部變數,在第一次使用時最好加上 var,已確認其有效範圍只在此函數內。
Hint 一個寫程式的好習慣,會省去後續無數的除錯時間,所以筆者在此不厭其煩、再提醒一次:函數內的變數,要盡量加上 var,以確保不會和函數外的變數相衝。
在函數外部定義的變數,無論是否有加 var,都會被視為是全域變數,因此可以不必刻意再去加 var。
JavaScript 程式設計與應用:用於網頁用戶端