2024-08-25 JavaScript 系列五:第3課 ── 變數作用域、箭頭函式、ES6 語法

JavaScript 系列五:第3課 ── 變數作用域、箭頭函式、ES6 語法
課程目標
認識變數作用域

認識函式的不同寫法與特性

課程內容
來認識一些程式語言觀念與名詞

1
2
3
4
5
6
<button onclick="action1()">
global scope
</button>
<button onclick="action2()">
local scope
</button>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
var counterA = 0;

function action1()
{
counterA = counterA + 1;
alert(counterA);
}

function action2()
{
var counterB = 0;
counterB = counterB + 1;
alert(counterB);
}

到 jsfiddle 跑跑看,會發現第一個計數器會不斷 +1 疊加上去;第二個計數器卻永遠顯示 1

這就是變數作用域的區別:變數宣告在很外面的,會在很大的範圍內都可使用這變數;變數宣告在很裡面的,只在裡面的範圍內才可使用這變數

宣告在最外面的稱為全域變數(global),反之則稱為區域變數(local)

目前為止的作業,其實你已經到處在寫 global 與 local 變數了,這觀念還算簡單、直觀

用精確的技術名詞來說明的話

在 ES6 (2015) 之前,JavaScript 中的變數作用域只有 Global Scope 跟 Function Scope 兩種

並且,在使用 var 關鍵字時,要留意一種名為 Hoisting 的現象,這是一種會讓人搞錯變數作用域的現象

在 ES6 之後,有了 const 與 let 兩種新關鍵字,宣告的變數為 Block Scope

使用這兩種關鍵字,就不會出現 Hoisting 的現象

我個人認為,Hoisting 是一個設計失敗的程式語言特性

應該要讓 JavaScript 引擎直接報錯、程式直接壞掉比較好

一般程式語言沒有 Hoisting 這種現象,此為 JavaScript 獨有特性

這是當年 Netscape 瀏覽器公司,為了衝市占率、歡迎大家亂寫 JS 程式碼的產物

我不想細談 Hoisting,反正改天你真的遇到問題,大概知道要往這方向研究就是了

實務上,現在大家都寫 const 與 let,比較不寫 var 了

所以 Function Scope 跟 Block Scope 的差別在哪?

簡單來說,這樣的程式碼,x 正常顯示,y 會報錯

if (true) {
var x = 1;
const y = 2;
}

alert(x);
alert(y);
var 會覺得變數作用域,只有 function 函式 內、外的差別,內就是同樣 local,外就是 global

const let 會覺得變數作用域,每次遇到 大括號 {} 都算一次內、外的差別,大括號裡面就是 local,裡面的裡面就是 local 中的 local

看不太懂沒關係,總之,變數宣告時,遇到 bug,就往前面找大括號,把變數搬來搬去,試試看,會慢慢搞懂的

本課先教你區分 global 與 local 兩種概念就好,這在大多數程式語言都是通用概念

在本系列教材內容以及作業中,const let var 隨便混著用,都可以

大概知道當前變數是 global 還是 local 就好

反正改天你真的遇到問題,大概知道要往這方向研究就是了

接下來談一談 JavaScript 中的函式

之前的課程中,有過這樣的範例

1
<button id="my-btn">Click me</button>
1
2
3
4
5
6
7
function myFunction()
{
alert('你點擊了按鈕!');
}

var btn = document.getElementById('my-btn');
btn.onclick = myFunction;

myFunction 被當成變數一樣,被指派給一個物件的屬性了

在很多程式語言中,函式是不能這樣使用的!函式永遠只能單獨加上小括號去執行 myFunction()

這個差別有點像是,其他程式語言認為變數是「名詞」,函式是「動詞」。那些語言認為這樣才能溝通、描述世界

而 JavaScript 認為變數是「名詞」,函式是「動詞」也是「動名詞」,也就是認為函式也是一種「名詞」。JavaScript 認為這樣才能溝通、描述世界

中文說「我開車」跟「開車很好玩」,沒有在管「開車」是動詞還是名詞,中文使用者就是習慣這樣溝通

英文說「I drive」跟「Driving is fun」,句子裡面主詞的部份一定要是名詞,如果想放動詞,就先改寫成 +ing 動名詞,英文使用者就是習慣這樣溝通

上面通通看不懂沒關係,反正知道各種程式語言,都是設計者與社群的主觀偏好,然後都能完成任務、各有不同長處短處就好

最後,跟大家談一下函式的不同寫法

1
2
3
4
5
6
7
8
9
10
11
function func1()
{
alert(1);
}

var func2 = () => {
alert(2);
}

func1();
func2();

ES6 之後有所謂的箭頭函式

他跟傳統寫法的主要差別,在於對於 this 關鍵字的認定

在工程師主流推崇 OOP(物件導向程式設計)的年代,this 的使用很巧妙、也很讓人困惑

實務上現在寫前端,比較少用 OOP 寫法,稍微偏向 FP(函數式程式設計)多一點,所以 this 問題變比較小

我不想細談 this 以及兩種函式寫法的差別,在本系列教材內容以及作業中,隨便混著用,都可以

反正改天你真的遇到問題,大概知道要往這方向研究就是了

課後作業
請使用 https://jsfiddle.net

用以下 html 為基礎(你可以稍微修改),id 跟 class 之類的你可以自由決定

simple counter:

1
2
3
4
5
6
7
8
9
<button>-</button>
<button>+</button>

<hr>

simple calculator:
<input type="text" />
<input type="text" />
<button>加/減/乘/除</button>

這邊有兩個小型應用程式

第一個應用程式,是簡單的計數器

第一次點擊 + 號按鈕,會用 alert 跳出 1
第二次點擊 + 號按鈕,會用 alert 跳出 2
依此類推,每次點 + 都會遞增,每次點 - 都會遞減
你會宣告一個全域變數,記錄這個累積的值,才能完成此功能
第二個應用程式,是簡單的計算機

有兩個欄位可以輸入數字
點擊按鈕,連續跳出四個 alert,分別顯示「加/減/乘/除」的計算結果
例如:輸入 6 與 2 -> alert 顯示 8 -> alert 顯示 4 -> alert 顯示 12 -> alert 顯示 3
你會宣告兩個區域變數,分別記錄兩個輸入的值,接著用來進行四種計算,才能完成此功能
做出以上功能,你就完成這次的課程目標了!