JavaScript 中的 嚴格模式

嚴格模式:使用嚴格模式的好處是能夠提前知道代碼中存在的錯誤,及時捕獲一些可能致使編程錯誤的 ECMAScript 行爲。javascript

嚴格模式的選擇使用

嚴格模式的編譯指示(pragma): "use strict";,支持嚴格模式的引擎會啓動這種模式,而不支持該模式的引擎就當遇到了一個未賦值的字符串字面量,會忽略這個編譯指示。java

  • 在全局做用域中(函數外部)給出這個編譯指示,則整個腳本都將使用嚴格模式。
  • 在函數做用域中給出這個編譯指示,則這個函數將使用嚴格模式
function test () {
 "use strict";
    ...
}
複製代碼

嚴格模式的規範

變量

  1. 不容許意外建立全局變量,給一個沒有聲明的變量賦值,那代碼在執行時就會拋出 ReferenceError
// 未聲明變量 
// 非嚴格模式:建立全局變量 
// 嚴格模式:拋出 ReferenceError
message = "Hello world! ";
複製代碼
  1. 不能對變量調用 delete 操做符
//刪除變量 
//非嚴格模式:靜默失敗 
//嚴格模式:拋出 ReferenceError
var color = "red";
delete color;
複製代碼
  1. 嚴格模式下對變量名也有限制,不能使用 implements、interface、let、package、 private、protected、public、static 和 yield 標識符做爲變量名,使用以上標識符做爲變量名會致使語法錯誤。

對象

  1. 爲只讀屬性賦值會拋出 TypeError
  2. 對不可配置的(nonconfigurable)的屬性使用 delete 操做符會拋出 TypeError
  3. 爲不可擴展的(nonextensible)的對象添加屬性會拋出 TypeError
  4. 使用對象字面量時,屬性名必須惟一
// 重名屬性 
// 非嚴格模式:沒有錯誤,以第二個屬性爲準 
// 嚴格模式:拋出語法錯誤
var person = {
    name: "Nicholas",
    name: "Greg"
};
複製代碼

函數

  1. 嚴格模式要求命名函數的參數必須惟一
//重名參數 
//非嚴格模式:沒有錯誤,只能訪問第二個參數 
//嚴格模式:拋出語法錯誤
function sum (num, num){
    // todo
}
複製代碼
  1. 在非嚴格模式下,修改命名參數的值也會反映到arguments對象中,而嚴格模式下這兩個值是徹底獨立的
//修改命名參數的值 
//非嚴格模式:修改會反映到 arguments 中 
//嚴格模式:修改不會反映到 arguments 中
function showValue(value) {
    value = "Foo";
    console.log(value); //"Foo" 
    console.log(arguments[0]); //非嚴格模式:"Foo",嚴格模式:"Hi"
}
showValue("Hi");
複製代碼
  1. 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);
複製代碼
  1. 嚴格模式對函數名也作出了限制,不容許用implements、interface、let、package、private、protected、public、static 和 yield 做爲函數名
  2. 只能在腳本的頂級和在函數內部聲明函數
//在 if 語句中聲明函數 
//非嚴格模式:將函數提高到 if 語句外部 
//嚴格模式:拋出語法錯誤
if (true){
    function doSomething(){
        // todo 
    }
}
複製代碼

eval()

  1. 在嚴格模式中,它在包含上下文中再也不建立變量或函數
//使用 eval()建立變量
//非嚴格模式:彈出對話框顯示 10
//嚴格模式:調用 alert(x)時會拋出 ReferenceError
function doSomething(){
    eval("var x=10");
    alert(x);
}
複製代碼
  1. 能夠在 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 值始終是指定的值,不管指定的是什麼值。app

// 訪問屬性
// 非嚴格模式: 傳入null, 函數的this值是全局對象
// 嚴格模式: 拋出錯誤,由於this的值爲 null
var color = "red";
function displayColor(){
    alert(this.color);
}
displayColor.call(null);
複製代碼

其餘變化

  1. 非嚴格模式下的 with 語句可以改變解析標識符的路徑。嚴格模式下,with 被簡化掉了
//with 的語句用法
//非嚴格模式:容許
//嚴格模式:拋出語法錯誤
with(location){
    alert(href);
}
複製代碼
  1. 嚴格模式去掉了 JavaScript 中的八進制字面量
//使用八進制字面量 
//非嚴格模式:值爲 8 
//嚴格模式:拋出語法錯誤
var value = 010;
複製代碼
  1. 嚴格模式下 parseInt()的行爲,八進制字面量在嚴格模式下會被看成以 0 開頭的十進制字面量
//使用 parseInt()解析八進制字面量 
//非嚴格模式:值爲 8 
//嚴格模式:值爲 10
var value = parseInt("010");
複製代碼
相關文章
相關標籤/搜索