嚴格模式
JavaScript 的嚴格模式是使用受限制的 JavaScript 的一種方式,從而隱式地退出“草率模式”。嚴格模式不僅僅是一個子集:這種模式有意地與普通情形下的代碼有所區(qū)別。(MDN)
嚴格模式為 JavaScript
提供了一個更嚴格的運行環(huán)境。
開啟嚴格模式后,部分特性會發(fā)生改變,如 this
指向 window
的函數(shù)不再指向 window
,而是變成了 undefined
。
function Test() {
'use strict';
console.log('this:', this);
}
Test(); // 輸出:this: undefined
1. 開啟嚴格模式
1.1 對單個 script 標簽或者 js 文件開啟嚴格模式
單個 js 文件或者 script 標簽的嚴格模式,可以通過在所有代碼執(zhí)行前加上 'use strict'
字符串開啟。
'use strict';
function Test() {
console.log('this:', this);
}
Test(); // 輸出:this: undefined
1.2 對一個函數(shù)開啟嚴格模式
在函數(shù)頂端協(xié)商 'use strict'
字符串,就可以打開整個函數(shù)的嚴格模式。
function testWith() {
'use strict';
var person = {
name: '鴿子天王',
age: 12,
};
var age = 11;
with (person) {
console.log(name);
console.log(age);
}
}
testWith();
在嚴格模式下是不提供 with
語句的調(diào)用的,所以這里會爆 Strict mode code may not include a with statement
錯誤。
2. 嚴格模式的規(guī)范
2.1 禁止使用 with
在嚴格模式下是禁止使用 with 語句的。
'use strict';
var person = {
name: '鴿子巨星',
};
with (person) {
console.log(name);
}
2.2 變量必須被聲明
在嚴格模式下,變量必須被聲明才能使用,否則會報錯。
// 非嚴格模式下
number = 1;
console.log(number); // 輸出:1
// 嚴格模式下
'use strict';
number = 1; // 報錯:ReferenceError: number is not defined
2.3 eval 會創(chuàng)建自己的作用域
非嚴格模式下的 eval 作用域是其本身所在的作用域,而嚴格模式下,eval 執(zhí)行過程中會創(chuàng)建一個新的作用域,并在結(jié)束后銷毀。
// 非嚴格模式下
var number = 1;
eval('var number = 3; console.log(number)'); // 輸出:3
console.log(number); // 輸出:3
// 嚴格模式下
'use strict';
var number = 1;
eval('var number = 3; console.log(number)'); // 輸出:3
console.log(number); // 輸出:1
2.4 函數(shù)的 arguments 不能被修改
在非嚴格模式下,函數(shù)的 arguments
可以被重新賦值,在嚴格模式下,做賦值操作會報錯。
function fn() {
console.log(arguments);
arguments = 1;
console.log(arguments);
}
fn(1, 2, 3);
'use strict';
function fn() {
console.log(arguments);
arguments = 1;
console.log(arguments);
}
fn(1, 2, 3);
2.5 函數(shù)的 this 規(guī)則有些變化
在 this
章節(jié)中討論了不同情況的指向,其中有一種情況函數(shù)的 this
是指向 window 的。
在嚴格模式中,這種情況下的 this
會變成 undefined
。
function testThis() {
console.log(this);
}
testThis();
// 嚴格模式下
'use strict';
function testThis() {
console.log(this);
}
testThis();
2.6 caller 與 arguments.callee 被禁用
arguments.caller
可以獲取到調(diào)用當(dāng)前函數(shù)的函數(shù)的引用(該屬性已經(jīng)被標準廢棄,不再使用了)。
arguments.callee
則可以獲取到當(dāng)前函數(shù)的引用。
這兩個屬性在嚴格模式下都被禁用。
function fn1() {
console.log(arguments.callee === fn1);
}
fn1();
'use strict';
function fn1() {
console.log(arguments.callee === fn1);
}
fn1();
2.7 刪除 configurable 為 false 的屬性時報錯
在非嚴格模式下,這種情況會直接忽略。
var obj = {};
Object.defineProperty(obj, 'prop', {
configurable: false,
value: 1,
});
console.log(obj);
delete obj.prop;
console.log(obj);
'use strict';
var obj = {};
Object.defineProperty(obj, 'prop', {
configurable: false,
value: 1,
});
console.log(obj);
delete obj.prop;
console.log(obj);
2.8 修改 writable 為 false 的屬性時會報錯
在非嚴格模式下,這種情況會直接忽略。
var obj = {};
Object.defineProperty(obj, 'prop', {
writable: false,
value: 1,
});
console.log(obj.prop);
obj.prop = 2;
console.log(obj.prop);
'use strict';
var obj = {};
Object.defineProperty(obj, 'prop', {
writable: false,
value: 1,
});
console.log(obj.prop);
obj.prop = 2;
console.log(obj.prop);
2.9 禁止書寫八進制的字面量
八進制的表示是在數(shù)字前面加一個 0
,但其實 ECMAScript
標準中并沒有這種表示法。
在 ES6 中提供了八進制數(shù)的表示方式,即在數(shù)字前加上 0o
前綴。
在嚴格模式下是禁止使用 0
前綴表示的八進制字面量的。
// 非嚴格模式中
var num = 010;
console.log(num); // 輸出:8
// 嚴格模式下
'use strict';
var num = 010;
console.log(num); // 輸出:8
2.10 新增了一些不能作為變量的關(guān)鍵字
許多關(guān)鍵字在非嚴格模式下是可以當(dāng)作變量名的。
var yield = 1;
console.log(yield);
'use strict';
var yield = 1;
console.log(yield);
根據(jù) MDN
提供的內(nèi)容,保留字有:
- implements
- interface
- let
- package
- private
- protected
- public
- static
- yield
3. 小結(jié)
對嚴格模式大多數(shù)需要注意的是他帶來的一些語法上的改變,特別是有些寫法,在之前是不會報錯的,開啟嚴格模式后就會報錯,如果沒有進行錯誤處理,就會導(dǎo)致程序的中斷。
以上對嚴格模式下的改變不一定是全部,可以參考 MDN 的文檔。