談談JavaScript中嚴格模式你應該遵照的那些事

嚴格模式

首先來了解一下嚴格模式是什麼?
嚴格模式是JavaScript中的一種限制性更強的變種方式,不是一個子集:它在語義上與正常代碼有明顯的差別,不支持嚴格模式的瀏覽器與支持嚴格模式的瀏覽器行爲上也不同,因此不要在未經嚴格模式特性測試狀況下使用嚴格模式,嚴格模式能夠與非嚴格模式共存,因此腳本能夠逐漸的選擇性加入嚴格模式瀏覽器

  • 嚴格模式的目的

首先,嚴格模式會將JavaScript陷阱直接變成明顯的錯誤,其次,嚴格模式修正了一些引擎難以優化的錯誤:一樣的代碼有些時候嚴格模式會比非嚴格模式下更快,第三,嚴格模式禁用了一些有可能在將來版本中定義的語法app

  • 全局開啓嚴格模式

在JavaScript中想要開啓嚴格模式,須要在全部代碼以前,定義一個不會賦給任何變量的字符串:ide

'use strict';//或者"use strict"

若是以前的JavaScript是非嚴格模式的話,建議不要盲目爲這段代碼開啓嚴格模式,這樣可能會出現問題,建議按一個個函數去開啓嚴格模式
也能夠爲某個指定的函數開啓嚴格模式:函數

//函數外部依舊是非嚴格模式
function fun(){
    'user strict';//開啓嚴格模式
}

在匿名函數中使用嚴格模式,至關於在全局開啓嚴格模式的變通實現方式測試

(function(){
    'use strict';//開啓嚴格模式
})();
  • 禁止意外建立變量

在嚴格模式下,不容許意外建立全局變量
下例代碼是非嚴格模式下意外建立全局變量優化

//未聲明的變量
result='這是一個沒用var聲明的全局變量';

下例代碼是嚴格模式下意外建立全局變量this

'use strict';//開啓嚴格模式
//嚴格模式下,意外建立全局變量,拋出ReferenceError
message='this is message';//ReferenceError: result is not defined
  • 靜默失敗轉爲異常

靜默失敗就是既不報錯也沒有任何效果,例如改變常量的值,在嚴格模式下,靜默失敗會轉換成拋出異常,注意:這個分瀏覽器,有些瀏覽器會,有些不會
下例代碼是非嚴格模式下的靜默失敗prototype

const PI=3.14;
PI=1.14;//靜默失敗
console.log(PI);//3.14

下例代碼是嚴格模式下的靜默失敗code

'use strict';//開啓嚴格模式

const PI=3.14;
PI=1.14;//拋出TypeError錯誤
  • 禁用delete關鍵字

在嚴格模式下,不能對變量使用delete運算符
下例代碼是非嚴格模式下使用delete運算符,結果會靜默失敗對象

var color='red';
delete color;

下例代碼是嚴格模式下使用delete運算符,結果會拋出異常

'use strict';//開啓嚴格模式

var color='red';
delete color;//SyntaxError: Delete of an unqualified identifier in strict mode.
  • 對變量名的限制

在嚴格模式下,JavaScript對變量名也有限制,特別不能使用implements,interface,let,packge,private,protected,public,stalic,yield這些內容做爲變量名,它們都是保留字,在ECMAScript的下一個版本中可能會用到它們,在嚴格模式下,使用這些標識符做爲變量名會致使語法錯誤

  • 不可刪除的屬性

在嚴格模式下,不能使用delete運算符刪除不可刪除的屬性
下例代碼是非嚴格模式下使用delete運算符刪除不可刪除的屬性,結果是靜默失敗

delete Object.prototype;

下例代碼是嚴格模式下使用delete運算符刪除不可刪除的屬性,結果會拋出異常

'use strict';//開啓嚴格模式
delete Object.prototype;//TypeError: Cannot delete property 'prototype' of function Object() { [native code] }
  • 屬性名必須惟一

在嚴格模式下,一個對象的全部屬性名在對象內必須惟一
下例代碼是非嚴格模式下重名屬性是容許的,最後一個重名的屬性決定其屬性值

var o={p:1,p:2};

下例代碼是嚴格模式下重名屬性被認爲是語法錯誤

'use strict';//開啓嚴格模式
var o={p:1,p:2};//不報錯可是語法錯誤
  • 只讀屬性的賦值

在嚴格模式下,不能爲一個只讀的屬性進行從新賦值
下例代碼是非嚴格模式爲只讀屬性從新賦值,結果會靜默失敗

var obj={};
Object.defineProperty(obj,'name',{
    value:'張三',
    writable:false
});//將屬性設置爲只讀
obj.name='李四';

下例代碼是嚴格模式下爲只讀屬性從新賦值,結果會拋出異常

'use strict';//開啓嚴格模式
var obj={};
Object.defineProperty(obj,'name',{
    value:'張三',
    writable:false
});//將屬性設置爲只讀
obj.name='李四';//TypeError: Cannot assign to read only property 'name' of object '#<Object>'
  • 不可擴展的對象

在嚴格模式下,不能爲不可擴展的對象添加新屬性
下例代碼是非嚴格模式爲不可擴展的對象添加新屬性,結果會靜默失敗

var obj={};
Object.preventExtensinons(obj);//將對象設置爲不可擴展
obj.name='張三';

下例代碼是嚴格模式下不可擴展的對象添加新屬性,結果會拋出異常

'use strict';//開啓嚴格模式

var obj={};
Object.preventExtensions(obj);//將對象變得不可擴展
obj.name='張三';//TypeError: Cannot add property name, object is not extensible
  • 參數名必須惟一

在嚴格模式下,要求命名函數的參數必須惟一
下例代碼是非嚴格模式下最後一個重名參數名會掩蓋以前的重名參數,以前的參數仍然能夠經過arguments[i]來訪問

function sum(a,a,c){}

下例代碼是嚴格模式下重名參數被認爲是語法錯誤

function sum(a,a,c){//語法錯誤
    'use strict';
    return a+a+c;//代碼運行到這裏會出錯:SyntaxError: Duplicate parameter name not allowed in this context
}
  • arguments的不一樣

在嚴格模式下,arguments對象的行爲也有所不一樣
1.非嚴格模式下,修改命名參數的值也會反應到arguments對象中
2.嚴格模式下,命名參數與arguments對象是徹底獨立的

function fun(value){
    value='haha';
    console.log(value);//haha
    console.log(arguments[0]);//非嚴格模式下 hah
                              //嚴格模式下 hello
}

showValue('hello');
``

 - arguments.callee()
在嚴格模式下,不能使用arguments對象的callee()方法
下例代碼是非嚴格模式下使用arguments對象的callee()方法,表示調用函數自己

var f=function(){

return arguments.callee;

};
f();

下例代碼是嚴格模式下使用arguments對象的callee()方法,結果會拋出異常

'use strict';//開啓嚴格模式
var f=function(){

return arguments.callee;

}
f();/TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them/

- 函數聲明的限制
在嚴格模式下,只能在全局域和函數域中聲明函數
下例代碼非嚴格模式下在任何位置聲明函數都是合法的

if(true){

function f(){}

}

下例是嚴格模式下在除全局域和函數域中聲明函數是語法錯誤

'use strict';//開啓嚴格模式
if(true){

function f(){}//語法錯誤,可是不報錯

}

- 增長eval做用域
在嚴格模式下,使用eval()函數建立的變量只能在eval()函數內部使用
下例代碼是非嚴格模式下eval()函數建立的變量在其餘位置可使用

eval('var n=40');
console.log(n);//40

下例代碼是嚴格模式下eval()函數建立的變量只能在eval()函數內部使用

'use strict';//開啓嚴格模式
eval('var n=40');
console.log(n);//ReferenceError: n is not defined

- 禁止讀寫
在嚴格模式下,禁止使用eval()和arguments做爲標識符,也不容許讀寫它們的值
1.使用var聲明
2.賦予另外一個值
3.嘗試修改包含的值
4.用做函數名
5.用做命名的函數的參數
6.在try...catch語句中用做例外名
在嚴格模式下,如下全部嘗試將致使語法錯誤:

'use strict';//開啓嚴格模式
eval=17;
arguments++;
++eval;
var obj={set p(arguments){}};
var eval;
try{}catch(arguments){}
function x(eval){}
function argunments(){}
var y=function eval(){}
var f=new Function('arguments','"use strict";return 20;');

- 抑制this
在非嚴格模式下使用函數apply()或call()方法時,null或undefined值會被轉換爲全局對象
在嚴格模式下,函數的this值始終是指定的值(不管什麼值)。

var color='red';
function sayColor(){

console.log(this.color);//非嚴格模式下 red
                    /*嚴格模式下:TypeError: Cannot 
                     read property 'color' of null*/

}

相關文章
相關標籤/搜索