# 變數
# let
與 const
let
被稱作為變數對應的值會產生變動,與其相對的是 const
即為常數對應的值不能再變動。
let
與 const
是 ES6 新增的語法,在環境允許的狀況下,這兩者會被優先使用。
JS 在紀錄變數上採取的是動態定型語言,變數本身沒有型態資訊,運用變數型態不須特別宣告。因此,x 的值由數字轉為字串也不會出錯。
> let x = 200 | |
undefined | |
> x = 'Zrn Ye' | |
'Zrn Ye' | |
> |
動態定型語言界中流行鴨子定型 (Duck typing):
「如果他走路像個鴨子,游泳像個鴨子,叫聲像鴨子,他就是鴨子。」
對基本型態來說,變數存了指定的值。
對複合型態來說,變數始終是個參考值,指定運算改變的是變數的參考對象。
因此,我們可以這麼做:
> let arr1 = [10,20,30] | |
undefined | |
> let arr2 = arr1 | |
undefined | |
> arr1[0] = 100 | |
100 | |
> arr2 | |
[ 100, 20, 30 ] | |
> |
對於 const
而言,宣告的常數只是不能重新設定該名稱的參考物件
如果物件可變動,物件依舊可以變動
> const arr = [ 1, 2, 3 ] | |
undefined | |
> arr[0] = 10 | |
10 | |
> arr | |
[ 10, 20, 30 ] | |
> |
如果沒有使用 let
或 const
先行宣告的話,會導致 ReferenceError
,表示變數尚未宣告
使用 let
時,若該變數已經存在,會發生 SyntaxError
。
> console.log(x) | |
Uncaught ReferenceError: x is not defined | |
> let y = 1000 | |
undefined | |
> let y | |
Uncaught SyntaxError: Identifier 'y' has already been declared | |
> |
如果宣告了變數但未給其定值,會給予 undefined
當作回傳值。
> let z | |
undefined | |
> z | |
undefined | |
> |
# var
在比 ES6 更早之前的版本,並沒有 const
或 let
,宣告皆為 var
,他有個古怪的個性:若原始檔案中儲存了以下程式碼也並不會出錯。
console.log(m); | |
var m = 10; | |
console.log(m); |
運行結果為:
undefined | |
10 |
var
在宣告前後範圍內都是有效的,這種行為被稱為提升。
絕大多數情況下,你不會希望有提升行為。如果是使用 let 就能避免:
console.log(m); //ReferenceError: Cannot access 'm' before initialization | |
let m; |
嚴格來說,使用 let
也會有提升行為,被稱作暫時死區。
# undefined
與 null
使用 let
或 var
,若宣告變數為定義值,變數會被賦予 undefined
。
若取得物件上不存在,也會回傳 undefined
。
對 undefined
使用 typeof
的結果是 'undefined'
,對 undefined
本身等於 undefined
:
> let x; | |
undefined | |
> x | |
undefined | |
> typeof undefined | |
undefined | |
> x === undefined | |
true | |
> |
在 JS 世界中, undefined
並非保留字喔,所以是可以被宣告跟定值的。
在 JS 世界裡還有一個怪值,稱作 null
。代表沒有物件。
舉個例子:若有變數本身是參考某個物件,若後來不想在那麼做,可以令變數參考 null
:
> let obj = {x: 10}; | |
undefined | |
> obj = null; | |
null | |
> |
但會這麼做的機會不多,比較常見的情況是透過 API 想找某條件的物件,而沒有找到時回傳 null
,這類 API 在瀏覽器中很多。
對 null
使用 typeof
會得到 'object'
,對於 null
也不能做任何的操作。
試圖存取 null
或呼叫方法,會引發 TypeError
# 嚴格模式
ES5 增加了嚴格模式,啟用嚴格模式後,若誤用了不好或早期規範不清的特性,會發生直譯或執行等相關錯誤。
JS 可以不使用 var
、 let
等宣告變數,例如:
x = 10; | |
console.log(x); // 顯示 10 |
然而,這不是個好特性,因為其宣告就會變成全域變數,絕大情況應該要避免。
因此,若在 .js
檔案的開頭加上 use strict
字串,即可避免此行為。
use strict
x = 10; //ReferenceError: x is not define | |
console.log(x); |
也可以在某些函式中使用嚴格模式,方式是在函式的本體開始處加上 use strict :
function foo(){ | |
'use strict' | |
// 其他程式碼 | |
} |
嚴格模式下,有許多被禁止的行為。
例如,ES6 規範中可以用 0o7 代表八進位整數,但在之前的版本你只需要在數字前加上 0 就可以表示八進位。若啟用了嚴格模式就會引起 SyntaxError
。
另外,如果要用 delete 刪除物件,失敗的話,會直接產生 TypeError
。
在嚴格模式下,不能使用保留字當作變數名稱,誤用的話,會引發 SyntaxError
。
還有許多嚴格模式下的限制,可以參考這個網站
除了避免錯誤外,嚴格模式也能加速運行程式的效能。
在使用 Node.js 的指令時,有個 --use_strict
選項可以開啟嚴格模式,適用於 REPL。
C:\Users\user\Desktop\js> node --use_strict | |
Welcome to Node.js v14.15.4 | |
Type ".help" for more information. | |
> let arr = [1, 2, 3]; | |
undefined | |
> delete arr.length | |
Thrown: | |
TypeError: Cannot delete property 'length' of [object Array] |