ECMAScript 5 引入了 strict mode ,如今已經被大多瀏覽器實現(從IE10開始)javascript
顧名思義,JavaScript 嚴格模式就是讓 JS 代碼以更嚴格的模式執行,不容許可能會引起錯誤的代碼執行。在正常模式下靜默失敗的代碼,嚴格模式下就會拋出錯誤。java
· 腳本文件範圍webpack
將
"use strict";
放在腳本文件的第一行。整個腳本文件就會以「嚴格模式」執行。
· 函數做用域範圍web
將
"use strict";
放在函數體的第一行,則整個函數以"嚴格模式"運行。
文件合併時,寫在腳本文件第一行的 "use strict";
來實現嚴格模式會失效,能夠將腳本文件的代碼放在一個當即執行表達式中。數組
(funciton() { "use strict"; ... })()
也就是,變量必須聲明後才能使用,正常模式直接賦值給一個未定義的變量時,會將變量定義爲全局變量。瀏覽器
"use strict"; var a = b = 3; // Uncaught ReferenceError: b is not defined 以上代碼等於: var a; b = 3; a = b;
this
關鍵字指向全局對象正常模式下,函數中若是沒有指明 this
對象,JS 則會將 this
隱式指向爲全局對象。若是綁定的值是非對象,將被自動轉爲對象再綁定上去,而 null 和 undefined
這兩個沒法轉成對象的值,將被忽略。安全
嚴格模式下,必須指明 this
的指向對象。若是沒有指明的話,this
的值爲 undefined
函數
var name = "foo"; function func() { "use strict"; this.name; // Uncaught TypeError: Cannot read property 'name' of undefined } func(); // 沒有加 new 關鍵字 new func(); function func() { return this } func() // window func.call(8) // Number {8} func.call(true) // Boolean {true} func.call("abcd") // {"abcd"} func.call(null) // window func.call(undefined) // window "use strict" function func() { return this } func() // undefined func.call(8) // 8 func.call(true) // true func.call(null) //null func.call(undefined) // undefined
禁止使用 arguments.callee、arguments.caller、fn.caller、fn.callee
;
在嚴格模式下,arguments.callee 是一個不可刪除屬性,並且賦值和讀取時都會拋出異常優化
function func() { "use strict"; func.caller; // 報錯 func.arguments; // Uncaught TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them } func()
沒法刪除 var 聲明的變量。this
在正常模式中,給對象的只讀屬性賦值, 刪除對象的不可設置屬性,添加不可擴展對象的新屬性,會靜默失敗。
可是在嚴格模式中,會拋出錯誤。
另外,字符串的屬性 length 也是隻讀屬性,修改後會報錯。
"use strict"; var str = "abc" str.length = 8 // Uncaught TypeError: Cannot assign to read only property 'length' of string 'abc' 'use strict'; var obj = Object.defineProperty({}, 'a', { value: 37, writable: false }); obj.a = 123; // Uncaught TypeError: Cannot assign to read only property 'a' of object '# 'use strict'; var obj = Object.defineProperty({}, 'p', { value: 37, configurable: false }); delete obj.p // Uncaught TypeError: Cannot delete property 'p' of #<Object> var obj = {}; Object.preventExtensions(obj); obj.title = "hello"; // Uncaught TypeError: Cannot add property title, object is not extensible
在正常模式中,對象的重名屬性,位置靠後會覆蓋位置靠前的重名屬性。函數也是,函數體查找到的參數,靠後的重名參數會覆蓋靠前的重名參數。
"use strict"; var o = { p: 1, p: 2 }; // IE報錯:strict 模式下不容許一個屬性有多個定義, 新版的 Chrome 和 firefox 並不會報錯,會採用覆蓋機制。 "use strict"; function func(a, a) { console.log(a) } func(1, 2) // IE報錯: strict 模式下不容許正式參數名稱重複。新版的 Chrome 和 firefox 並不會報錯,會採用覆蓋機制。
JavaScript 支持動態綁定,也就是 JavaScript 的屬性和方法是在運行時肯定,而不是在編譯時肯定。
因而,JavaScript 嚴格模式禁用了 with 語句, 由於使用了 with 語句,with 語句塊中變量沒法肯定是外部全局變量仍是傳入的對象屬性。
"use strict"; var x = 17; with (obj) // !!! 語法錯誤 { // 若是沒有開啓嚴格模式,with 中的這個x會指向 with 上面的那個 x,仍是obj.x? // 若是不運行代碼,咱們沒法知道,所以,這種代碼讓引擎沒法進行優化,速度也就會變慢。 x; // Uncaught SyntaxError: Strict mode code may not include a with statement }
eval 關鍵字再也不會給上層函數(surrounding function)或者全局引入一個新的變量。在嚴格模式中,eval 語句會建立本身的一個做用域,eval 裏的變量只能在 eval 內部使用。
嚴格模式規定名稱爲 eval 和 arguments 不能經過程序語法被綁定(be bound)或賦值
嚴格模式下,參數的值不會隨 arguments 對象的值的改變而變化。
正常模式中,對參數從新賦值,會修改 arguments 類數組對象下的參數值。同時,修改 arguments 類數組對象的值,也會修改函數參數的值。
嚴格模式下,不只參數的值不會隨着 arguments 類數組對象的變化而變化,參數的變化也不會引發 arguments 對象的變化,arguments 對象會記住參數的傳入初始值。
function func(a) { "use strict" a = 8; // arguments[0] = 8 return [a, arguments[0]] } func(3) // [8, 3] function func(a) { "use strict" arguments[0] = 8 return [a, arguments[0]] } func(3) // [3, 8]
ES5 的嚴格模式只容許在全局做用域或函數做用域聲明函數。也就是說,不容許在非函數的代碼塊內聲明函數。
if (true) { function add() { } } add() for (var i = 0; i < 5; i++){ function f2() { } // !!! 語法錯誤 f2(); } 以上代碼在嚴格模式是禁止的,可是在 ES6 中,是容許在代碼塊中聲明函數的。
嚴格模式中一部分字符變成了保留的關鍵字。這些字符包括implements, interface, let, package, private, protected, public, static
和yield
。在嚴格模式下,你不能再用這些名字做爲變量名或者形參名
function private() {"use strict" } //Uncaught SyntaxError: Unexpected strict mode reserved word
嚴格模式可以幫助咱們寫出更安全,更有規範的代碼,則應該避免一些危險的寫法,採用更好的寫法:
如今的 webpack 會在打包的時候默認是嚴格模式,因此如今不用再手動寫 use strict
了。嚴格模式能幫助咱們以更規範的方式書寫代碼,可是不管是否嚴格模式,都應該注意代碼的規範,避免隱式 bug 的出現。
2018/02/08 @Starbucks