嚴格模式

qq_46670991發表於2020-10-29

嚴格模式是什麼

嚴格模式是JavaScript中的一種限制性更強的變種方式。嚴格模式不是一個子集: 它在語義上與正常程式碼有著明顯的差異。

不支援嚴格模式的瀏覽器與支援嚴格模式的瀏覽器行為上也不一樣,所以不要在未經嚴格模式特性測試情況下使用嚴格模式。

嚴格模式可以與非嚴格模式共存,所以指令碼可以逐漸的選擇性加入嚴格模式。

嚴格模式的目的

首先,嚴格模式會將JavaScript陷阱直接變成明顯的錯誤。

其次,嚴格模式修正了一些引擎難以優化的錯誤:同樣的程式碼有些時候嚴格模式會比非嚴格模式下更快。

第三,嚴格模式禁用了一些有可能在未來版本中定義的語法。

開啟嚴格模式

全域性開啟嚴格模式

需要在所有程式碼之前,定義一個不會賦值給任何變數的字串;

 "use strict";	//或者'use strict'
開啟嚴格模式 - 作用於全域性作用域
// "use strict"
// 定義一個變數 - 不使用var關鍵字
a = 100;

console.log(a);
function fn(){
  // 開啟嚴格模式 - 作用於函式作用域
  "use strict"
  v = 200;
  console.log(v);
}

fn();

函式開啟嚴格模式

也可以為某個指定的函式開啟嚴格模式,如下程式碼示例:

//函式外依舊是非嚴格模式
function doSomething(){
	"user strict";//開啟嚴格模式
	//其他程式碼
}

在匿名函式中使用嚴格模式,相當於在全域性開啟嚴格模式的變通實現方式。

(function(){
	"use strict";//開啟嚴格模式
})(); 

變數

禁止意外建立變數

在嚴格模式下,不允許意外建立全域性變數。

  • 如下程式碼是非嚴格模式下意外建立全域性變數。

    //未宣告變數
    message = "this is message";
    
  • 如下程式碼是嚴格模式下意外建立全域性變數。

    "use strict";//開啟嚴格模式
    //嚴格模式下,意外建立全域性變數,丟擲ReferenceError
    message = "this is message"; 
    

案例:

// 開啟嚴格模式
"use strict";

v = 100;
console.log(v);

function fn(){
    
    // 在非嚴格模式:在函式作用域中定義變數 - 不使用var關鍵字 -> 自動將其提升為全域性變數
    w = 200;
    console.log(w);
}
fn();
console.log(w);

靜默失敗轉為異常

所謂靜默失敗就是既不報錯也沒有任何效果,例如改變常量的值。在嚴格模式下,靜默失敗會轉換成丟擲異常。

  • 如下程式碼是非嚴格模式下的靜默失敗。

    const Pl = 3.14;
    Pl = 1.14; //靜默失敗
    console.log(Pl); //3.14
    
  • 如下程式碼是嚴格模式下的靜默失敗。

    "use strict"; //開啟嚴格模式
    const Pl =3.14;
    Pl =1.14; //丟擲IypeError錯誤
    

禁用delete關鍵字

在嚴格模式下,不能對變數使用delete運算子。

  • 如下程式碼是非嚴格模式下使用delete運算子,結果會靜默失敗。

    var color = "red";
    delete color; 
    
  • 如下程式碼是嚴格模式下使用delete運算子,結果會丟擲異常。

    "use strict";//開啟嚴格模式
    
    var color = "red";
    delete color;	//丟擲ReferenceError錯誤
    

對變數名的限制

在嚴格模式下,JavaScript對變數名也有限制。特別不能使用如下內容作為變數名:

implementsinterfacelet
packageprivateprotected
publicstaticyield

上述內容都是保留字,在ECMAScript的下一個版本中可能會用到它們。
在嚴格模式下,使用上述標示符作為變數名會導致語法錯誤。

物件

不可刪除的屬性

在嚴格模式下,不能使用delete運算子刪除不可刪除的屬性。

  • 如下程式碼是非嚴格模式下使用delete運算子刪除不可刪除的屬性,結果會靜默失敗。

    delete Object.prototype;
    
  • 如下程式碼是嚴格模式下使用delete運算子符刪除不可刪除的屬性,結果 會丟擲異常。

    "use strict";//開啟嚴格模式
    delete object.prototype; //丟擲IypeError錯誤
    

屬性名必須唯一

在嚴格模式下,一個物件內的所有屬性名在物件內必須唯一。

  • 如下程式碼是非嚴格模式下重名屬性是允許的,最後一個重 名的屬性決定其屬性值。

    var o = {p:1,p:2 };
    
  • 如下程式碼是嚴格模式下重名屬性被認為是語法錯誤。

    "use strit";	// 開啟嚴格模式
    varo={p:1,p:2 };	//!!語法錯誤
    

只讀屬性的賦值

在嚴格模式下,不能為一個只讀的屬性進行重新賦值。

  • 如下程式碼是非嚴格模式為只讀屬性重新賦值,結果會靜默失敗。

    var obj1 = {};
    
    Object.defineProperty(obj1, "x", { value: 42, writable: false });
    //將屬性設定為只讀
    
    obj1.x=9;
    
  • 如下程式碼是嚴格模式下為只讀屬性重新賦值,結果會丟擲異常。

    "use strict";//開啟嚴格模式
    
    varobj1={};
    Object.defineProperty(obj1, "x", { value: 42, writable: false });//將屬性設定為只讀
    
    obj1.x= 9; //丟擲TypeError錯誤
    

不可擴充套件的物件

在嚴格模式下,不能為不不可擴充套件的物件新增新屬性。

  • 非嚴格模式為不可擴充套件的物件新增新屬性,結果會靜默失敗。

    var obj = {};
    Object.preventExtensions(obj);  //將物件變得不可擴充套件
    obj.newProp = 'ohai';
    
  • 嚴格模式不可擴充套件的物件新增新屬性,結果會丟擲異常

    "use strict";	//開啟嚴格模式
    
    var obj = {};
    Object.preventExtensions(obj);	//將物件變得不可擴充套件
    obj.newProp = "ohai";	//丟擲TypeError錯誤
    

函式

引數名必須唯一

嚴格模式下,命名函式的引數必須唯一

  • 非嚴格模式下最後一個重名引數名會掩蓋之前的重名引數,之前的引數仍然可以通過arguments[i]來訪問.

    function sum(a,a,c){}
    
  • 嚴格模式下重名引數被認為是語法錯誤

    function sum(a,a,c){	// !語法錯誤
    	"use strict"
    	
    	return a + a + c;	// 程式碼執行到這裡會報錯
    }
    

arguments的不同

在嚴格模式下,arguments物件的行為也有所不同。

  • 非嚴格模式下,修改密碼引數的值也會有反應到arguments物件中。
  • 嚴格模式下,命名引數與arguments物件是完全獨立的。
//開啟嚴格模式
"use strict";

function fn(value){
    var value = '二狗子';
    console.log(value); //二狗子 -> 就近原則

    /*
        *非嚴格模式下  -  arguments物件獲取引數的值與形參有關的
            * 如果區域性變數與形參名相同 - 根據就近原則進行獲取
        *嚴格模式下   -  arguments物件獲取引數的值與形參無關的
    
    */
   console.log(arguments[0]);   //二狗子
}
fn('大狗子');   //大狗子

arguments.callee()

在嚴格模式下,不能使用arugments物件的callee()方法。

  • 非嚴格模式下使用arugments物件的callee()方法,表示呼叫函式本身。

    var f = function(){
    	return arguments.callee;
    } ;
    
  • 嚴格模式下使用arugments物件的callee()方法,結果會丟擲異常。

    "use strict";	//開啟嚴格模式
    
    var f = function(){
    	return arguments.callee;
    };
    f();	//丟擲TypeError錯誤
    

函式宣告的限制

在嚴格模式下,只能在全域性域和函式域中宣告函式。

  • 非嚴格模式下在任何位置宣告函式都是合法的。

    if (ture){
    	function f(){}
    }
    
  • 嚴格模式下在除全域性域和函式域中宣告函式是語法錯誤。

    "use strict";	//開啟嚴格模式
    
    if (true){
    	function f()  {}	//語法錯誤
    }
    

eval()函式

增加eval()作用域

在嚴格模式下,使用eval()函式建立的變數只能在eval()函式內部使用。

  • 非嚴格模式下eval()函式建立的變數在其他位置可以使用

    eval("var x = 42");
    console.log(x);	//42
    
  • 嚴格模式下eval()函式建立的變數只能在eval()函式內部使用。

    "use strict";       //開啟嚴格模式
    
    eval("var x = 42");
    console.log(x);	//丟擲ReferenceError錯誤
    

argument物件

禁止讀寫

嚴格模式下,禁止使用eval()和arguments作為識別符號,也不允許讀寫他們的值。

  • 使用var宣告
  • 賦予另一個值
  • 嘗試修該包含的值
  • 用作函式名
  • 用作命名的函式的引數
  • 在try…catch語句中用作例外名

嚴格模式下,導致語法錯誤的:

"use strict";       //開啟嚴格模式

eval = 17;
arguments++;
++eval;
var obj = {set p(arguments){} };
var eval;
try {} catch (arguments){}
function x(exal){}
function arguments() {}
var y = function eval(){};
// var f = new Function(
//     "arguments","'use strict';return 17;"
// );

this關鍵字

抑制this

  • 非嚴格模式下使用函式的apply()或call()方法時, null或undefined值會被轉換為全域性物件。
  • 嚴格模式下,函式的this值始終是指定的值(無論什麼值)。
var color = 'red';

function sayColor(){
	console.log(this.color);	//非嚴格模式下red
}							//嚴格模式下 丟擲錯誤

sayColor.call(null);

相關文章