Function statement & Function expression|函數陳述句 & 函數表示式 IIFE
兩大觀念先記熟:
JavaScript的函數(function)是一種可被呼叫物件(object)。
物件(object)是一種值(value)。
整理自Udemy熱門課程JavaScript 全攻略:克服 JS 的奇怪部分。
Function statement 函數陳述句
function greet(){
console.log('hi')
}
上述這段程式碼告訴我們:greet是一個會印出hi
的function。
Function expression 函數表示式
跟函數陳述句很不一樣的地方在於,函數表示式執行後會產生一個值(value)
1+2
跟a = 3
都是函數表示式,因為都會產出一個value。
匿名函式
函數陳述句的寫法長這樣,還沒被呼叫前會被hoisting,所以無論是在哪裡greet()
呼叫他,都會出現hi:
greet() //hi
function greet(){
console.log('hi')
}
greet() //hi
還有一種寫法是用一個變數把後面的匿名函式包起來,這就是函數表示式,因為呼叫他後會傳整個物件。
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.log
出Hello 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打開來了,結果還是一堆人叫我去做牙助啦、保險啦、汽車測試工程師(??)啦、或是當鋪@@
繼續努力ㄌ!