Web前端入門第 55 問:JavaScript 嚴格模式與非嚴格模式區別
JavaScript 默認是非嚴格模式的,可以通過 "use strict"; 啟用嚴格模式。此聲明語句可以放在 JS 文件頂部,也可以放在函數內部。
啟用嚴格模式
1、外部腳本在 JS 文件開頭聲明,內部腳本在 <script> 標簽開頭聲明,聲明后所有 JS 代碼啟用嚴格模式:
"use strict";
console.log('Hello World!');
錯誤寫法:
console.log("test");
"use strict"; // 置于代碼之后的聲明,嚴格模式不生效!
2、在函數內部聲明函數啟用嚴格模式,此時本函數體內部的 JS 代碼將啟用嚴格模式:
function strictFunc() {
"use strict"; // 函數級嚴格模式
let x = 10;
y = 20; // ReferenceError: y is not defined
}
function nonStrictFunc() {
y = 20; // 非嚴格模式下隱式創建全局變量(不推薦)
}
錯誤寫法:
if (true) {
"use strict"; // 無效!嚴格模式無法在塊級作用域啟用
x = 10; // 非嚴格模式下隱式創建全局變量
}
3、模塊化腳本(ES6 Modules)無需顯式聲明,默認啟用嚴格模式:
// module.js(無需寫 "use strict")
export default function() {
x = 10; // ReferenceError: x is not defined
}
4、類(ES6 Class)聲明或類方法內部無需顯式聲明默認啟用嚴格模式:
class MyClass {
constructor() {
x = 10; // ReferenceError: x is not defined
}
}
為何 JS 代碼會有兩種不同的解析結果?
這就不得不提到歷史原因了,JS 之父創造 JavaScript 時,僅用了 10 天時間,這久導致了 JS 在后來使用中發現了一些問題,又由于瀏覽器的版本迭代必須要兼顧一些舊的代碼(不可能瀏覽器來一個版本更新,直接把所有網站一棒打死),所以就有了 嚴格模式 的出現,這個模式的用途就是告訴瀏覽器,我這個網站的代碼你按照 嚴格模式 來解析,無需考慮歷史兼容性,可能存在的隱式錯誤可以先告訴我。
嚴格模式 vs 非嚴格模式
主要區別如下:
變量聲明
非嚴格模式:未聲明的變量賦值會隱式創建全局變量。
嚴格模式:未聲明的變量賦值會拋出 ReferenceError。
<script>
function test1 () {
y = 10; // 聲明為全局變量
}
test1();
console.log(y); // 10
</script>
<script>
function test2 () {
"use strict";
x = 10; // ReferenceError: x is not defined
}
test2();
console.log(x); // test2 報錯,此行代碼不執行
</script>
靜默錯誤轉顯式錯誤
刪除不可刪除的屬性:delete Object.prototype; 在嚴格模式下報錯。
重復參數名:function(a, a) {} 在嚴格模式下報語法錯誤。
只讀屬性賦值:NaN = 1; 在嚴格模式下報錯。
<script>
function test1 (a, a) {
delete Object.prototype;
NaN = 1;
}
test1();
</script>
<script>
"use strict";
function test2 (a, a1) { // 報錯 SyntaxError
delete Object.prototype; // 報錯 TypeError
NaN = 1; // 報錯 TypeError
}
test2();
</script>
this 指向
非嚴格模式:全局函數中 this 指向全局對象(如 window)。
嚴格模式:全局函數中 this 為 undefined。
<script>
function test1 () {
console.log(this); // 瀏覽器中指向 Window 對象,nodejs 中指向 global 對象
}
test1();
</script>
<script>
"use strict";
function test2 () {
console.log(this); // undefined
}
test2();
</script>
eval 和 arguments 限制
eval 變量泄漏:嚴格模式下 eval 中的變量不會污染外部作用域。
禁用 arguments.callee:防止遞歸調用導致性能問題。
<script>
function test1 () {
eval('var a = 10');
console.log(arguments.callee); // 指向函數本身
console.log(a); // 10
}
test1();
</script>
<script>
"use strict";
function test2 () {
eval('var a = 10');
console.log(arguments.callee); // 報錯 TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them
console.log(a); // ReferenceError: a is not defined
}
test2();
</script>
其他限制
八進制表示:禁止 0123,需用 0o123。
with 語句:嚴格模式下禁用,避免作用域混亂。
保留字限制:如 interface、private 等不能作為變量名。
<script>
function test1 () {
console.log(0123); // 83
with (Math) {
console.log(random()); // 輸出隨機數
}
var interface = 'str';
console.log(interface); // str
}
test1();
</script>
<script>
"use strict";
function test2 () {
console.log(0123); // SyntaxError: Octal literals are not allowed in strict mode.
with (Math) { // SyntaxError: Strict mode code may not include a with statement
console.log(random());
}
var interface = 'str'; // SyntaxError: Unexpected strict mode reserved word
console.log(interface);
}
test2();
</script>
寫在最后
建議始終啟用嚴格模式,強制更安全的編碼實踐,避免隱式錯誤,提升代碼質量。

浙公網安備 33010602011771號