Minghsin University of Science and Technology
Uedu Main Site
Explore Uedu
Student Console
Register as Member/Login
Research Informed Consent Center
Survey Center
Educational Big Data Challenge
Claim or create a course
Try a Scenario Task
Support & Messages
Uptime Data

UeduGPTs

--

Jupyters

1

Local AI

--

Uedu Code

--

明新科大 AQI 70 24°C PM2.5 19
AI Reply Desktop Notifications

Show a desktop notification when the AI TA finishes replying

Chat Message Notifications

Notify me when classmates post messages in the forum

Sound notification

Play an alert sound whenever there is a new notification

Unit 03

變數宣告:var、let、const

識別字規則、作用範圍與提升
Interaction實作 20 minute(s)

Learning Objectives

  • 用 let、const 宣告變數,說明 const 鎖住的是「指向哪個值」而不是物件內容
  • 依識別字規則替變數命名,知道哪些名稱不能用
  • 分辨 var 與 let 在作用範圍、重複宣告與提升上的差異
  • 說明沒有宣告就指定值會發生什麼事,以及嚴格模式的作用

變數:替資料取一個名字

變數(variable)是一個名字,指向記憶體裡的一個值。程式用名字找到值,值可以是數字、字串、物件等任何資料。 JavaScript 有三種宣告方式:

宣告 能不能重新指定值 作用範圍 什麼時候用
const 不能 區塊 預設用它:大部分的值宣告之後就不會再換
let 可以 區塊 值之後會改變,例如計數器、迴圈變數
var 可以 函式 舊寫法,新程式不要用;看懂舊程式碼即可

let 和 const 是 ES2015(也叫 ES6)加入的。在那之前只有 var,它有一些容易造成錯誤的特性,這一課後半段會一一看到。 現在的習慣是:先用 const,需要改值時才改成 let,不用 var。

JavaScript 是弱型別(動態型別)語言:宣告變數時不必寫型別,同一個 let 變數可以先放數字、之後再放字串。

三種宣告與重新指定

一步一步播放,看右邊的框架。注意第一步:程式還沒執行到第 4 行,var 宣告的 school 就已經在框架裡了,值是 undefined;let、const 宣告的變數要執行到那一行才出現。

const:不能重新指定,但物件內容可以改

const 有兩條規則:

  1. 宣告時一定要給值:const PI; 是語法錯誤(SyntaxError),程式一行都不會執行。
  2. 不能重新指定:PI = 3; 會得到 TypeError: Assignment to constant variable.

但要注意,const 鎖住的是「這個名字指向哪一個值」。如果值是物件或陣列,物件裡面的內容仍然可以修改: 可以改屬性、可以 push 新元素,只是不能讓這個名字改指向另一個物件。

const 的物件與陣列

user 和 scores 都是 const,看第 3~7 行:右邊的物件內容一直在變,沒有出現任何錯誤。第 11 行想讓 scores 指向一個新陣列,這才是 const 不允許的事。

想一想:let 與 const

1.

下面的程式會印出什麼?出錯時選錯誤的名稱。

const PI = 3.14;
PI = 3;
console.log(PI);
2.

下面的程式會印出什麼?

const list = [1, 2];
list.push(3);
console.log(list);
3.

下面的程式會印出什麼?出錯時選錯誤的名稱。

let total = 1;
let total = 2;
console.log(total);
第 1 次作答

識別字的規則

變數、函式、屬性的名字叫做識別字(identifier)。規則如下:

  • 可以用英文字母、數字、$、_,第一個字元不能是數字:score1、_count、$btn 可以,1st 不行
  • 大小寫不同就是不同的名字:score 和 Score 是兩個變數
  • 不能用保留字:例如 let、const、var、if、for、function、return、class、new、typeof、true、false、null
  • 不能有空白或連字號:user name、user-name 都不行(- 會被當成減號)
  • 允許 Unicode 文字,所以 let 名字 = 'Amy'; 也能執行;但團隊合作時一般還是用英文命名

命名習慣:變數與函式用小駝峰(camelCase)如 totalPrice、isLoggedIn;不會改變的設定值常用全大寫加底線,如 MAX_SIZE。

重複宣告:var 可以重複宣告同一個名字(後面的會蓋掉前面的,容易不小心覆蓋別人的變數);let、const 重複宣告是語法錯誤。

沒有宣告就使用:

  • 讀取一個從來沒宣告的變數:ReferenceError: x is not defined
  • 沒宣告就直接指定值(total = 100;):一般模式下不會出錯,而是在全域物件上建立一個屬性,等於偷偷產生全域變數
  • 在程式或函式開頭寫 'use strict'; 進入嚴格模式(ES5 加入),沒宣告就指定值會直接出錯,可以及早發現打錯字
  • delete 是用來刪除物件的屬性,不能刪除用 var、let、const 宣告的變數

沒有宣告就指定值:一般模式與嚴格模式

sloppy 函式裡的 total 沒有宣告。看第 6 行:函式已經結束,全域框架裡卻多了一個 total。strict 函式開頭寫了 'use strict',同樣的寫法就出錯了。

想一想:識別字與重複宣告

1.

下列哪一個可以當作變數名稱?

2.

下面的程式會印出什麼?

var a = 1;
var a = 2;
console.log(a);
3.

下面的程式會印出什麼?

let Score = 1;
let score = 2;
console.log(Score + score);
第 1 次作答

var 與 let 的主要差異

var let
作用範圍 函式作用域:在 if、for 的區塊裡宣告,整個函式都看得到 區塊作用域:只在宣告它的 { } 裡面有效
重複宣告 可以 不行(SyntaxError)
重新指定值 可以 可以
宣告之前讀取 得到 undefined(被提升) ReferenceError(「尚未初始化」)

提升(hoisting):JavaScript 執行一段程式之前,會先找出裡面所有的宣告。var 宣告的變數一開始就建立好,值是 undefined; let、const 也會先被找出來,但在執行到宣告那一行之前不能使用,這段期間叫做暫時性死區(temporal dead zone)。 let 的設計讓「在宣告前就使用」變成明顯的錯誤,而不是悄悄得到 undefined。

下面兩個範例,第一個看提升,第二個看區塊作用域(作用域在 j12 會完整介紹)。

提升:var 是 undefined,let 是「尚未初始化」

第一步就看右邊:a 和 b 都已經在框架裡,a 是 undefined,b 標示「尚未初始化」。第 3 行讀 a 沒有問題;第 7 行在宣告前讀 b,就出現 ReferenceError。

區塊作用域:var 會跑出區塊,let 不會

這是投影片 Lab03 的例子。注意第 5 行:區塊裡的 let x 遮住了外面的 x,框架裡只看得到區塊裡的那一個;離開區塊(第 8 行)之後,外面的 x 又出現了。if 裡用 var 宣告的 leak,在 if 結束後還看得到。

想一想:提升與區塊

1.

下面的程式會印出什麼?

console.log(n);
var n = 5;
2.

下面的程式會印出什麼?出錯時選錯誤的名稱。

console.log(n);
let n = 5;
3.

下面的程式會印出什麼?

function test() {
  var x = 1;
  {
    let x = 2;
  }
  console.log(x);
}
test();
第 1 次作答

實作:選對 let 與 const

一杯飲料 50 元,價格不會變;杯數會改變。補上兩個宣告,並在中間把杯數改成 5(不要再宣告一次)。完成後應該印出 2 杯 100 和 5 杯 250。

你的輸出
預期輸出

重點精華回顧

  • 宣告變數用 const(不會重新指定)或 let(之後會改值);var 是舊寫法,看得懂即可。
  • const 宣告時一定要給值、不能重新指定;但 const 的物件與陣列,內容仍然可以修改。
  • 識別字可以用字母、數字、$、_,不能以數字開頭、不能用保留字,大小寫不同就是不同的名字。
  • var 可以重複宣告、是函式作用域、宣告前讀取得到 undefined;let 不能重複宣告、是區塊作用域、宣告前讀取是 ReferenceError。
  • 沒宣告就指定值會偷偷產生全域變數;用 'use strict' 嚴格模式可以讓這種錯誤立刻現形。
這一課完成了!
Next lesson:基本型別與型別轉換
你目前沒有登入,學習進度只存在這個瀏覽器。 Login 後,進度會跟著帳號,換電腦也看得到。