[JS] Function基本介紹-1
TL;DR
本篇介紹Function的宣告及建立方式:
- 具名函式(函式陳述式)
- 匿名函示(函式表達式)。
參考資料
相關連結
- JavaScript 的資料型別與資料結構 | MDN
函式簡介
在JS中,物件型別包含物件以及其子型別,例如陣列、函式。 函式與一般物件不同的地方在於:
- 多了被呼叫的能力,且可以傳入參數
- 包含了一個程式碼片段
function <function name>(參數){
程式碼片段
}
以下提供簡單的函式範例:
function fn(parameter){
var localVariable='函示fn內的區域變數';
console.log(this,localVariable);
return `回傳一段${parameter}`;
}
let data=fn('外部傳入的字串');
console.log(data) //"回傳一段外部傳入的字串"
值得注意的是,fn('外部傳入的字串')
這段,因為在執行函式的時候,就會回傳(return)內容,所以本身就是一個表達式。
- 可被呼叫的能力(be invoked)
- 程式碼片段
- 函式名稱(可選用)
函式陳述式
我們可以透過function
保留字,來宣告一個函式。這種方式稱為函式陳述式。又因為透過這種方式所宣告的函式,一定會具備一個名字,所以又稱為具名函式。
以下提供一個簡單的函數陳述式範例:
function fnA(){
console.log('函數陳述式','具名函式');
console.log(fnA)
}
fnA();
// 函數陳述式 具名函式
// ƒ fnA(){
// console.log('函數陳述式','具名函式');
// console.log(fnA)
// }
可以看到在 Line:8 (即對應的 Line:3 )。
印出的結果為f fnA(){...}
。可以看到該函式是具有名稱的。
執行結果圖示
在hoisting的章節也有介紹到,使用function宣告所創建的函式,在創造階段就已經包含完整的程式碼在記憶體內了。
提升的順序也會在變數之前。所以不管在程式碼中的哪個位置透過陳述式宣告函式,都可以執行。這是因為hoisting會自動將該具名函式提升到最上方。
函式表達式
另外,我們也可以透過表達式的方式來宣告一個函式。範例如下:
const fnB=function(){
console.log('函式表達式','匿名函式');
console.log(fnB);
}
fnB();
// 函式表達式 匿名函式
// ƒ (){
// console.log('函式表達式','匿名函式');
// console.log(fnB);
// }
可以看到 Line:8 印出f (){...}
。該函式不具有名稱。
這是因為我們使用表達式的方式來宣告函式,我們首先先定義了一個變數(fnB),接著我們才宣告一個函式並將該函式賦予到變數上。此時我們就不用定義函式的名稱。這種方式又稱為函式表達式。
執行結果圖示
因為是先宣告變數,才將函式賦予到變數 上,所以在hoisting的順序上也有所不同。這部分請參考hoisting的文章。
需要注意,函式表達式也可以具有名稱!
所以函式陳述式等同於具名函式,但是函式表達式不一定等於匿名函式。
具名函式表達式
先前有提到,不是所有的函式表達式都是匿名函式。
範例如下:
const fnC=function fnD(){
console.log('fnC',fnC);
console.log('fnD',fnD);
}
fnC();
// fnC ƒ fnD(){
// console.log('fnC',fnC);
// console.log('fnD',fnD);
// }
// fnD ƒ fnD(){
// console.log('fnC',fnC);
// console.log('fnD',fnD);
// }
首先,我們先宣告一個變數fnC,接著使用表達式的方式,來將具名函式fnD給賦予到變數fnC上。
可以發現我們在執行fnC的時候,印出來的結果都會是fnD
。這是因為fnD是這個函式的名稱!!
在變數fnC內存放的其實是名叫fnD的函式。
執行結果圖示
注意事項
具名函式表達式無法在函式外被調用!
舉例來說,如果程式碼如下:
const fnC=function fnD(){
console.log('fnC',fnC);
console.log('fnD',fnD);
}
fnC(); //可以順利執行
fnD(); //無法順利執行!!! fnD沒有被定義
執行結果圖示
綜合範例
範例一
let num=1;
const giveMeMoney=function giveMoreMoney(coin){
num+=1;
console.log('執行GiveMeMoney',`現在的num是${num}`,`現在的coin是${coin}`);
return coin>100? coin: giveMoreMoney(num*coin);
}
console.log(giveMeMoney(30));
// 執行GiveMeMoney 現在的num是2 現在的coin是30
// 執行GiveMeMoney 現在的num是3 現在的coin是60
// 執行GiveMeMoney 現在的num是4 現在的coin是180
// 180
其實上述寫法將函式內的三元運算子撰寫為giveMeMoney(num*coin)
結果也是相同的。
所以實務上使用函式表達式時可以直接省略函式名稱