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