Function statement & Function expression|函數陳述句 & 函數表示式 IIFE

Wendy Chang
Wendy Loops
Published in
6 min readJan 9, 2023

兩大觀念先記熟:

JavaScript的函數(function)是一種可被呼叫物件(object)。

物件(object)是一種值(value)。

整理自Udemy熱門課程JavaScript 全攻略:克服 JS 的奇怪部分

Function statement 函數陳述句

function greet(){
console.log('hi')
}

上述這段程式碼告訴我們:greet是一個會印出hi的function。

Function expression 函數表示式

跟函數陳述句很不一樣的地方在於,函數表示式執行後會產生一個值(value)

1+2a = 3都是函數表示式,因為都會產出一個value。

匿名函式

函數陳述句的寫法長這樣,還沒被呼叫前會被hoisting,所以無論是在哪裡greet()呼叫他,都會出現hi:

greet() //hi

function greet(){
console.log('hi')
}

greet() //hi

JavaScript面試考題:Hoisting是什麼?

還有一種寫法是用一個變數把後面的匿名函式包起來,這就是函數表示式,因為呼叫他後會傳整個物件。

var anonymousGreet = function(){
console.log('hi')
}

要呼叫這個匿名函數的時候,因為已經有var過了,所以JS就會知道這個匿名函數的位址在哪裡,只要直接呼叫即可:

var anonymousGreet = function(){
console.log('hi')
}

anonymousGreet() //hi

但是跟函數陳述句很不一樣的地方就在於hoisting

如果把呼叫的anonymousGreet()放到表示式前的話,會發生什麼事?

anonymousGreet()

var anonymousGreet = function(){
console.log('hi')
}

anonymousGreet在創造階段時,會被預設為undefined

var anonymousGreet;

anonymousGreet();

undefined是一個純值,不能被當成function執行,所以會報錯。
但在之後宣告anonymousGreet是一個物件之後,再呼叫它就可以執行了。

var anonymousGreet = function(){
console.log('hi')
}

anonymousGreet() //hi

IIFE

Immediately invoked function expressions(IIFE)意思是立即呼叫的函數表示式,無論是函數陳述句還是函數表示式,都需要額外呼叫他,如下:

// function statement 陳述句
function greet(name) {
console.log('Hello ' + name);
}
greet('John');

// function expression 表示式
var greetFunc = function(name) {
console.log('Hello ' + name);
};
greetFunc('John');

而IIFE就不需要另外呼叫,寫法是在表示式後面直接寫上(),代表直接執行,()內可以帶入參數,例如這邊帶入的是字串’John’

var greeting = function(name) {

return 'Hello ' + name;

}('John');

console.log(greeting);

這時候greeting是一個變數,直接用console.log(greeting)就可以把Hello John印出來!

IIFE更簡潔的寫法

如果沒有用var xxx = 去把匿名函式接起來:

function(name) {
return 'Hello ' + name;
}

就會報錯:他需要一個名字啊!!
syntax parser從第一個字開始閱讀,發現開頭是function,所以預設這會是個函數陳述句,結果發現不是,所以報錯。

如何避免報錯

讓syntax parser閱讀時,第一個字不是function,而是(

(function(name) {
return 'Hello ' + name;
});

()是一個運算子,只使用於表示式中,陳述句不會用到(),例如if就是一個陳述句:

if(表示式){ 
// do someting
}

直接呼叫表示式

()內的function後方加入()執行,()內可以帶入參數:

var firstname = 'Wendy';

(function(name) {
console.log('Hello ' + name) ;
}(firstname));

這樣就會直接console.logHello Wendy

IIFE中的變數

在global和IIFE中各var一個變數greeting

var firstname = 'Wendy';
var greeting = 'global Hello';


(function(name) {
var greeting = 'IIFE Hello';
console.log(greeting + ' '+name)
}(firstname));

console.log(greeting)

會發現IIFE中的greeting’IIFE Hello’,global的greeting’global Hello’

這是因為兩個變數所在的執行環境不同,所以IIFE中的變數不會跟global變數相互汙染。

耶耶,終於知道這兩種寫法的差別了!以前超眼殘根本看不出來差別好好笑!
距離正式求職還有不到一個月的時間,最近又把104打開來了,結果還是一堆人叫我去做牙助啦、保險啦、汽車測試工程師(??)啦、或是當鋪@@

繼續努力ㄌ!

參考資料:
JavaScript 全攻略:克服 JS 的奇怪部分

--

--

Wendy Chang
Wendy Loops

什麼都寫ㄉ前端工程師 / 影片剪輯師 / 自媒體經營者 斗內網址:https://p.ecpay.com.tw/E35E9DE