JavaScript 相較是個自由的語言,在學習語法時會發現,咦 明明規則是這樣,怎麼那樣也可以?
在 2009 年的 ECMAScript 5 中新增了嚴格模式,就像加入了一位風紀股長,以前睜一隻眼閉一隻眼容許的灰色地帶語法,現在會毫不留情的被指出!
(你 那個黃頭髮的! 衣服扎進去)
此篇文將會分享:
在嚴格模式下,以往一些容易造成混淆或是默認的不良語法,現在會直接跳出 error 訊息,修正了一些會阻礙引擎最佳化的問題,也為了之後可能的變動鋪路,像是新增了一些保留字。
嚴格模式提高了整體 code 的穩定與安全程度。
以下截圖是 ECMA 針對 strict mode 的規範
要怎麼套用嚴格模式呢?
作法很簡單,只要加上 'use strict'
這段語法。
可以放在 全域 或是 區域函數 內,但請務必放在最開頭,依照規範說明,這樣底下的 code 才能有效的被視為 strict mode code
特別的是加在區域函數內的 'use strict'
並不會影響到全域,而是只在該 function 的範圍內實施嚴格模式!
但,就算沒有特別加上 'use strict'
,在某些情況也可能默默進入嚴格模式,依照規範的第 2 和 3 點,在 module 模組 下 以及 使用 classDeclaration, classExpression, 這時候都會視為 strict mode code!
好的,那瞭解了嚴格模式的使用和作用範圍後,接下來 就來看看到底哪些行為是在嚴格模式下不被允許的吧~
在一般模式下,JS 接受賦予值到一個未經宣告過的變數,但這件事在嚴格模式下被禁止了,會直接拋出變數未定義的錯誤訊息
//一般模式
cookie = 'oreo'; // 無var,let,const宣告
console.log(cookie) // 'oreo'
//嚴格模式
'use strict'
cookie = 'oreo' // Uncaught ReferenceError: cookie is not defined
在一般模式下使用 delete 刪除變數和函數只會跑出 false,不會有實質上的效果但也不會報錯,但在嚴格模式下會偵測此錯誤,並拋出錯誤訊息
//一般模式
let cookie = 'oreo';
delete cookie; // false
console.log(cookie) // 還是可以印出 'oreo'
//嚴格模式
'use strict'
let cookie = 'oreo';
let function x (a,b) {};
delete cookie; // SyntaxError: Delete of an unqualified identifier in strict mode
delete x; // SyntaxError: Delete of an unqualified identifier in strict mode
一般模式下若 function 放入了兩個相同的參數名稱,後位的參數值會取代前面的參數,但在嚴格模式下禁止了重複的參數命名
//一般模式
function plus(x,x,y) {
return (x+y);
}
plus(1,2,4) // 取第二個x值, 得到6
//嚴格模式
'use strict'
function plus(x,x,y) {
return (x+y);
}
plus(1,2,4) // SyntaxError: Duplicate parameter name not allowed in this context
不接受使用八進制的數字實字及逃脫字元
//一般模式
let octalNumeric = 010;
let escape = '\010';
//嚴格模式
'use strict'
let octalNumeric = 010; // SyntaxError: Octal literals are not allowed in strict mode.
let escape = '\010'; // SyntaxError: Octal escape sequences are not allowed in strict mode.
某些屬性規定只能 read-only 或 get-only,若強行對他們做寫入修改,一般模式下並不會產生作用但也不會報錯,但這件事在嚴格模式下將會明確的被當錯誤丟出!
對 read-only property 寫入新的值
//一般模式
const obj = {};
Object.defineProperty(obj, "x", {value:0, writable:false}); // 不允許寫入
obj.x = 3.14;
console.log(obj.x) // 0, 不會報錯但新賦予的值也不會被寫入
//嚴格模式
"use strict";
const obj = {};
Object.defineProperty(obj, "x", {value:0, writable:false});
obj.x = 3.14; // TypeError: Cannot assign to read only property 'x' of object '#<Object>'
對 getter 讀取的 property 寫入新的值
// 一般模式
const obj = {
get x() {
return 0;
},
};
obj.x = 3.14;
console.log(obj.x); // 0, 不會報錯但新賦予的值也不會被寫入
//嚴格模式
'use strict'
const obj = {
get x() {
return 0;
},
};
obj.x = 3.14; // TypeError: Cannot set property x of #<Object> which has only a getter
//一般模式
let eval = 1;
let argument = 2;
//嚴格模式
'use strict'
let eval = 1;
let argument = 2;
SyntaxError: Unexpected eval or arguments in strict mode
目前還沒使用過 with
語法,依 MDN with語法 的說明 : with
在一般模式下也不建議使用,有容易造成混淆的問題,但也僅僅是不建議而已,還是可以使用
而在嚴格模式下是完全禁止 with
語法
//一般模式
let a, x, y;
const r = 10;
with (Math) {
a = PI * r * r;
x = r * cos(PI);
y = r * sin(PI / 2);
}
console.log(a) // 314.1592653589793
console.log(x) // -10
console.log(y) // 10
//嚴格模式
"use strict";
let a, x, y;
const r = 10;
with (Math) {
a = PI * r * r;
x = r * cos(PI);
y = r * sin(PI / 2);
}
// SyntaxError: Strict mode code may not include a with statement
在使用一般的函式呼叫時,this 這時會指向全域也就是 global 或 window,但在嚴格模式下會顯示為 undefined
// 一般模式
function myFunction() {
alert(this);
}
myFunction(); // alert視窗跳出 [object Window]
// 嚴格模式
"use strict";
function myFunction() {
alert(this);
}
myFunction(); // alert視窗跳出 undefined
另外也預留了一些之後 JavaScript 語法上會用到的保留字,在嚴格模式下不能使用,否則跳出 SyntaxError: Unexpected strict mode reserved word
以下是嚴格模式在各大瀏覽器的支援程度,除了 IE9 以外都支援此語法,而其實 'use strict'
在不支援的環境下也僅是為普通字串,頂多無作用但不會跳出錯誤訊息