嚴格模式
:使用嚴格模式的好處是可以提早知道程式碼中存在的錯誤,及時捕獲一些可能導致程式設計錯誤的 ECMAScript 行為。
嚴格模式的選擇使用
嚴格模式的編譯指示(pragma): "use strict";
,支援嚴格模式的引擎會啟動這種模式,而不支援該模式的引擎就當遇到了一個未賦值的字串字面量,會忽略這個編譯指示。
- 在全域性作用域中(函式外部)給出這個編譯指示,則整個指令碼都將使用嚴格模式。
- 在函式作用域中給出這個編譯指示,則這個函式將使用嚴格模式
function test () {
"use strict";
...
}
複製程式碼
嚴格模式的規範
變數
- 不允許意外建立全域性變數,給一個沒有宣告的變數賦值,那程式碼在執行時就會丟擲 ReferenceError
// 未宣告變數
// 非嚴格模式:建立全域性變數
// 嚴格模式:丟擲 ReferenceError
message = "Hello world! ";
複製程式碼
- 不能對變數呼叫 delete 操作符
//刪除變數
//非嚴格模式:靜默失敗
//嚴格模式:丟擲 ReferenceError
var color = "red";
delete color;
複製程式碼
- 嚴格模式下對變數名也有限制,不能使用 implements、interface、let、package、 private、protected、public、static 和 yield 識別符號作為變數名,使用以上識別符號作為變數名會導致語法錯誤。
物件
- 為只讀屬性賦值會丟擲 TypeError
- 對不可配置的(nonconfigurable)的屬性使用 delete 操作符會丟擲 TypeError
- 為不可擴充套件的(nonextensible)的物件新增屬性會丟擲 TypeError
- 使用物件字面量時,屬性名必須唯一
// 重名屬性
// 非嚴格模式:沒有錯誤,以第二個屬性為準
// 嚴格模式:丟擲語法錯誤
var person = {
name: "Nicholas",
name: "Greg"
};
複製程式碼
函式
- 嚴格模式要求命名函式的引數必須唯一
//重名引數
//非嚴格模式:沒有錯誤,只能訪問第二個引數
//嚴格模式:丟擲語法錯誤
function sum (num, num){
// todo
}
複製程式碼
- 在非嚴格模式下,修改命名引數的值也會反映到arguments物件中,而嚴格模式下這兩個值是完全獨立的
//修改命名引數的值
//非嚴格模式:修改會反映到 arguments 中
//嚴格模式:修改不會反映到 arguments 中
function showValue(value) {
value = "Foo";
console.log(value); //"Foo"
console.log(arguments[0]); //非嚴格模式:"Foo",嚴格模式:"Hi"
}
showValue("Hi");
複製程式碼
- arguments.callee 和 arguments.caller,在非嚴格模式下,這兩個屬性一個引用函式本身,一個引用呼叫函式。而在嚴格模式下,訪問哪個屬性都會丟擲 TypeError
//訪問 arguments.callee
//非嚴格模式:沒有問題
//嚴格模式:丟擲 TypeError
function factorial(num){
if (num <= 1) {
return 1;
} else {
return num * arguments.callee(num-1)
}
}
var result=factorial(5);
複製程式碼
- 嚴格模式對函式名也做出了限制,不允許用implements、interface、let、package、private、protected、public、static 和 yield 作為函式名
- 只能在指令碼的頂級和在函式內部宣告函式
//在 if 語句中宣告函式
//非嚴格模式:將函式提升到 if 語句外部
//嚴格模式:丟擲語法錯誤
if (true){
function doSomething(){
// todo
}
}
複製程式碼
eval()
- 在嚴格模式中,它在包含上下文中不再建立變數或函式
//使用 eval()建立變數
//非嚴格模式:彈出對話方塊顯示 10
//嚴格模式:呼叫 alert(x)時會丟擲 ReferenceError
function doSomething(){
eval("var x=10");
alert(x);
}
複製程式碼
- 可以在 eval()中宣告變數和函式,但這些變數或函式只能在被求值的特殊作用域中有效,隨後就將被銷燬
"use strict";
var result = eval("var x=10, y=11; x+y");
alert(result); // 21
複製程式碼
eval 和 arguments
嚴格模式已經明確禁止使用 eval 和 arguments 作為識別符號,也不允許讀寫它們的值。
// 把 eval 和 arguments 作為變數引用
// 非嚴格模式: 沒問題,不出錯
// 嚴格模式: 丟擲語法錯誤
var eval = 10;
var arguments = "Hello world!";
複製程式碼
抑制this
在非嚴格模式下使用函式的 apply()或 call()方法時,null 或 undefined 值會被轉換為全域性 物件。而在嚴格模式下,函式的 this 值始終是指定的值,無論指定的是什麼值。
// 訪問屬性
// 非嚴格模式: 傳入null, 函式的this值是全域性物件
// 嚴格模式: 丟擲錯誤,因為this的值為 null
var color = "red";
function displayColor(){
alert(this.color);
}
displayColor.call(null);
複製程式碼
其他變化
- 非嚴格模式下的 with 語句能夠改變解析識別符號的路徑。嚴格模式下,with 被簡化掉了
//with 的語句用法
//非嚴格模式:允許
//嚴格模式:丟擲語法錯誤
with(location){
alert(href);
}
複製程式碼
- 嚴格模式去掉了 JavaScript 中的八進位制字面量
//使用八進位制字面量
//非嚴格模式:值為 8
//嚴格模式:丟擲語法錯誤
var value = 010;
複製程式碼
- 嚴格模式下 parseInt()的行為,八進位制字面量在嚴格模式下會被當作以 0 開頭的十進位制字面量
//使用 parseInt()解析八進位制字面量
//非嚴格模式:值為 8
//嚴格模式:值為 10
var value = parseInt("010");
複製程式碼