[JS奇怪的世界]No.27 函數陳述句與函數表示式

前言

上一章節我們已經明白函數就是物件,接下來課程將利用這個觀念讓我們做一些有趣又強大的事情,但是開始前我們必須瞭解函數陳述句與函數表示式的差異。

表示式 (Expressions)

Expressions

表示式 (Expressions)的意思是說,輸入之後能夠直接回傳值的一串程式,簡單來講就是只要我們輸入那一大串程式碼之後能夠直接回傳值,那它就是一個表示式

所以我們來看一下範例程式碼。

1
var a

就這樣,接下來我們就可以開啟瀏覽器在 F12 開發者工具中輸入 console.log(a),可以看到 a 目前儲存在記憶體中。

那表示式到底是什麼?表示式會回傳一個值,所以當我們這樣打

1
a = 3;

記得中間這是一個等號運算子,它會將 3 賦予至 a,然後再回傳一個值,所以我們就會出現一個值,那就是 3,而這行為就是表示式,所以其實前面 var a 是有回傳值的,那個值就是 undefined

等號運算子

陳述句 (Statements)

那陳述句呢?讓我們看看這個範例程式 ↓

1
2
3
if (a === 3) {
console.log('Hello');
}

a === 3 其實也是一個表示式,因為它也可以直接回傳值(當條件為 true 或 false),但 if 這個指令就不一樣了,它是一個陳述句,它不會直接回傳一個值,所以我們也不能把它設置為一個變數。

1
2
3
var b = if (a === 3) {
console.log('Hello');
}

這邊我們可以瞭解到一件觀念

  • 函數表達式 會直接回傳值。
  • 函數陳述句 不會回傳值,而是做其他事情。

函數陳述句

在 JavaScript 中我們都知道函數是一個物件,而函數裡面也有函數陳述句與函數表示式,這兩個東西非常的強大,首先我們先來做一個函數陳述句 ↓

1
2
3
function greet() {
console.log('hi');
};

當它被執行時並不會回傳任何值(此處執行並不是 greet(),而是在講全域環境建立),函數陳述句的特色就是通過 hoisting 特性,先儲存進記憶體中,直到你執行這個函數函數。

在前面章節有講過變數及函數有提升特性,所以可以在函數陳述句之前呼叫 greet

1
2
3
4
5
greet();

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

函數表示式

接下來就是函數表示式。

1
2
3
var anonymousGreet = function() {
console.log('hi');
};

看到這邊要注意一個觀念「函數就是物件」(附帶一提這也是人家講的匿名函數。)

(匿名函數就是沒有名稱的函數。)

那該如何觸發這個函數表示式?

1
anonymousGreet();

這就是函數表達式,感覺與函數陳述句很像吧。

讓我們整合一下兩個程式碼 ↓

1
2
3
4
5
6
7
8
9
10
11
greet();

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

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

anonymousGreet();

相信你一定會發現這兩者差異並不大,但我們存在 anonymousGreet 中的匿名函數,只要加上括號就可以觸發函數。

匿名函數就是一個表示式

而函數陳述句與函數表示式最大差異在於,函數陳述句僅僅只是將函數存入記憶體,它只是知道[oh!這裡有一個函數],然後透過 hoisting 提升到最前面儲存至記憶體內就沒了。

但函數陳述句則是不一樣,它並不會因為 hoisting 提升到最前面,只有變數會被提升,陳述句則在原本地方

所以如果將 anonymousGreet() 移至 var anonymousGreet 之前會發生什麼事情?

1
2
3
4
anonymousGreet()
var anonymousGreet = function greet () {
console.log('hi');
};

這時候我們要去想一下,當執行環境被創造時哪兩個東西會被提升,變數與函數然後提升,那結果會是什麼?

anonymousGreet

我們會得到 TypeError: anonymousGreet is not a function,而不是 hi

所以實際將程式碼解開來看就會像這樣 ↓

1
2
3
4
5
var anonymousGreet;
anonymousGreet()
anonymousGreet = function greet () {
console.log('hi');
};

這就是為什麼會顯示 TypeError: anonymousGreet is not a function,因為變數 anonymousGreet 被提升到最前面且賦予 undefined,那 undefined 本身是不能夠執行,所以才會出現錯誤。

除非直到 anonymousGreet =anonymousGreet 才會被正確的被重新設定,所以我們又得知一個結論。

函數表示式並不會被提升

這邊我們在一次要強調函數就是物件,所以可以這樣玩

1
2
3
4
5
6
7
function log(a){
console.log(a);
}

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

那該如何執行輸出 hi?只要這樣就可以了。

1
2
3
4
5
6
7
function log(a){
a();
}

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

圖源

JavaScript 全攻略:克服 JS 奇怪的部分

0%