JavaScript Strict Mode (嚴格模式)

Strict Mode(嚴格模式)是 ES5 引入的功能,透過在程式碼開頭加上 'use strict' 字串來啟用。嚴格模式會讓 JavaScript 引擎以更嚴格的規則執行程式碼,幫助你避免一些常見錯誤,寫出更安全的程式碼。

如何啟用嚴格模式

整個 script 啟用

在 script 或 JavaScript 檔案的最開頭加上 'use strict'

'use strict';

// 這個檔案中的所有程式碼都會以嚴格模式執行
var x = 10;
'use strict' 必須放在程式碼的最開頭,前面只能有註解或空白。如果放在其他程式碼後面就無效。

單一函式啟用

也可以只在特定函式內啟用嚴格模式:

function strict() {
    'use strict';
    // 這個函式內以嚴格模式執行
}

function notStrict() {
    // 這個函式不是嚴格模式
}

ES6 模組自動啟用

使用 ES6 模組 時,模組內的程式碼會自動以嚴格模式執行,不需要手動加上 'use strict'

嚴格模式的限制

1. 變數必須宣告

在一般模式下,忘記用 var 宣告變數會自動建立全域變數,這是常見的錯誤來源。嚴格模式會直接拋出錯誤:

'use strict';

x = 10;  // ReferenceError: x is not defined

// 正確做法
var x = 10;

2. 禁止刪除變數和函式

'use strict';

var x = 10;
delete x;  // SyntaxError

function foo() {}
delete foo;  // SyntaxError

3. 禁止重複的參數名稱

'use strict';

// SyntaxError: Duplicate parameter name not allowed
function sum(a, a) {
    return a + a;
}

4. 禁止八進位字面值

'use strict';

var num = 010;  // SyntaxError

// 如果需要八進位,使用 0o 前綴(ES6)
var num = 0o10;  // 8

5. 禁止對只讀屬性賦值

'use strict';

var obj = {};
Object.defineProperty(obj, 'x', { value: 10, writable: false });
obj.x = 20;  // TypeError: Cannot assign to read only property

// 對不可擴展的物件新增屬性也會報錯
Object.preventExtensions(obj);
obj.y = 20;  // TypeError: Cannot add property y

6. 禁止刪除不可配置的屬性

'use strict';

delete Object.prototype;  // TypeError

7. eval 有獨立作用域

在嚴格模式下,eval() 中宣告的變數不會洩漏到外部作用域:

'use strict';

eval('var x = 10;');
console.log(x);  // ReferenceError: x is not defined

8. this 預設是 undefined

在一般模式下,函式中的 this 如果沒有指定會指向全域物件(瀏覽器中是 window)。嚴格模式下,this 會是 undefined

'use strict';

function showThis() {
    console.log(this);
}

showThis();  // undefined(一般模式會是 window)

9. 禁止使用保留字作為變數名

'use strict';

// 這些都會報錯
var implements = 1;
var interface = 1;
var let = 1;
var package = 1;
var private = 1;
var protected = 1;
var public = 1;
var static = 1;
var yield = 1;

10. 禁止 with 語句

'use strict';

// SyntaxError
with (obj) {
    x = 10;
}

為什麼要使用嚴格模式?

  1. 提早發現錯誤:許多原本會被忽略的錯誤會立即拋出,更容易除錯
  2. 避免意外的全域變數:忘記 var 不再會自動建立全域變數
  3. 更安全:禁止了一些不安全的功能(如 with 語句)
  4. 為未來版本做準備:保留字不能作為變數名,避免與未來語法衝突
  5. 效能優化:某些情況下,JavaScript 引擎可以對嚴格模式程式碼做更好的優化

實際範例

範例一:防止意外的全域變數

// 一般模式 - typo 會建立全域變數
var userName = 'Mike';
userNmae = 'John';  // 打錯字,建立了新的全域變數
console.log(userName);  // 還是 'Mike'

// 嚴格模式 - 會報錯
'use strict';
var userName = 'Mike';
userNmae = 'John';  // ReferenceError

範例二:this 的安全性

// 一般模式 - 可能意外修改全域物件
function setName(name) {
    this.name = name;
}
setName('Mike');  // 意外在 window 上設定了 name

// 嚴格模式 - 會報錯
'use strict';
function setName(name) {
    this.name = name;
}
setName('Mike');  // TypeError: Cannot set property 'name' of undefined

相容性

嚴格模式被所有現代瀏覽器支援。'use strict' 對於不支援的舊瀏覽器來說只是一個普通的字串,不會造成錯誤,所以可以安全地使用。

建議

現代 JavaScript 開發中,建議總是使用嚴格模式。如果你使用 ES6 模組或現代打包工具(如 Webpack、Rollup),通常會自動套用嚴格模式。即便如此,在撰寫傳統 script 時,手動加上 'use strict' 仍是好習慣。