ECMAScript 5 最先引入了 「嚴格模式」(strict mode)的概念。經過嚴格模式,能夠在函數內部存在的錯誤,及時捕獲一些可能致使編程錯誤的 ECMAScript 行爲。javascript
理解嚴格模式的規則很是重要,ECMAScript 的下一個版本將以嚴格模式爲基礎制定。支持嚴格模式的瀏覽器包括 IE10+、Firefox 4+、Safari 5.1+ 和 Chrome。java
想要開啓嚴格模式,直接在做用域開始的位置寫上字符串 "use strict"
;編程
在全局模式下開啓:瀏覽器
"use strict";
複製代碼
在局部模式下開啓(在函數中打開嚴格模式):安全
function fn(){
"use strict";
// 其餘代碼
}
複製代碼
在嚴格模式下,何時建立變量以及怎麼建立變量都是有限制的。不容許意外建立全局變量(就是嚴格模式下消除了僞全局變量)。瞭解僞全局變量請閱讀【三分鐘帶你深刻理解 JavaScript 的函數做用域】markdown
// 注意:(function(){})()是一個匿名函數
(function () {
a = 10;
console.log(a);
})(); // 結果:10
(function () {
"use strict";
a = 10;
})(); // 報錯:ReferenceError: a is not defined
複製代碼
在非嚴格模式下,即便變量 a 前面沒有 var 關鍵字,即便沒有將它定義爲某個全局對象的屬性,也能將 a 建立爲僞全局變量使用。dom
在嚴格模式下,若是給一個沒有聲明的變量賦值,那代碼在執行的時候就會拋出錯誤 ReferenceError
(引用錯誤)函數
嚴格模式要求命名函數的參數必須惟一。post
// 非嚴格模式
(function () {
function foo(a ,a, b){
console.log(a,b);
}
foo(1,2,3)
})(); // 結果: 2 3
// 嚴格模式
(function () {
"use strict";
function foo(a ,a, b){
console.log(a,b);
}
foo(1,2,3)
})(); // 報錯:SyntaxError: Duplicate parameter name not allowed in this context
複製代碼
在非嚴格模式下,這個函數聲明不會拋出錯誤。經過參數名只能訪問重複參數的第二個參數,要訪問第一個重複參數,必須經過 arguments
對象。ui
在嚴格模式下,上面函數參數的不規範會拋出 SyntaxError
(對象表明嘗試解析語法上不合法的代碼的錯誤)
arguments
的分離在嚴格模式下,arguments
對象的行爲有所不一樣。
在非嚴格模式下,修改命名參數的值也會反映到 arguments
對象中,而嚴格模式下這兩個值是徹底獨立的。
// 非嚴格模式
// arguments 會受到 形參賦值的影響;
(function(){
function foo(a,b){
a = 20;
console.log(a,b); // 20 2
console.log(arguments[0],arguments[1]); // 20 2
}
foo(1,2)
})();
// 嚴格模式
(function(){
"use strict";
// 形參 和 arguments 之間的區別;
// 形參是變量能夠隨意賦值;
// arguments 就是對應實參的關鍵字獲取全部的實參,進行使用,不會被改變;
function foo(a,b){
a = 20;
console.log(a,b); // 20, 2
console.log(arguments[0],arguments[1]); // 1, 2
}
foo(1,2)
})();
複製代碼
以上代碼中,函數 foo()
傳入兩個參數 a,b 。調用這個函數時傳入了兩個參數「1,2」,這個值賦個了對應的變量。而在函數內部,a 的值被修改成「20」。
在非嚴格模式下,這個修改的值也會改變 arguments[0]
的值; 但在嚴格模式下,arguments[0]
的值仍然是傳入的值。
arguments
的嚴格使用,部分功能禁用了淘汰了 arguments.callee
和 arguments.caller
。 在非嚴格模式下,這兩個屬性一個是引用函數自己,一個是引用調用函數。而在嚴格模式下,這兩個屬性都被禁用了。
(function(){
function foo(){
// arguments.callee 指向了當前的函數自己;
console.log(arguments.callee);
}
foo()
})(); // 結果: ƒ foo(){console.log(arguments.callee);}
(function(){
"use strict";
function foo(){
// 禁用掉了大部分arguments的屬性;
console.log(arguments.callee)
}
foo()
})(); // 報錯:TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments
複製代碼
相似的,嘗試讀寫函數的 caller
屬性也會拋出 TypeError
(類型錯誤)。本身能夠嘗試一下呦!
this
的嚴格(抑制this
)JavaScript 中一個最大的安全問題,也是最容易讓人迷惑的地方就是在某些狀況下如何抑制this
的值。
在非嚴格模式下,null
或 undefined
值會被轉換爲全局對象 window
。而在嚴格模式下,函數的 this
值始終是指定的值,不管指定的是什麼值。
(function(){
function foo(){
// this 指向 window;
console.log(this);
}
foo()
})(); // 結果:Window
(function(){
"use strict";
function foo(){
// 禁用指向了 window 的 this,讓 this 指向 undefined
console.log(this);
}
foo()
})(); // 結果:undefined
複製代碼
在之後的編程之中,this
最沒有用的指向就是全局對象 window
。
with(){}
語句在非嚴格模式下的 with
語句可以改變解析標識符的路徑,但在嚴格模式下,with
被拋棄了。所以,在嚴格模式下使用 with
會致使語法錯誤。
(function(){
with(Math){
// 能夠省略對象前置;
console.log(random()); // => Math.random()
console.log(PI); // => Math.PI
}
})();
// 嚴格模式之下禁用 with(){}
(function(){
"use strict";
with(Math){
console.log(random());
console.log(PI);
}
})(); // 報錯:Uncaught SyntaxError: Strict mode code may not include a with statement
複製代碼
在非嚴格模式下,with
能夠改變做用域鏈,他可讓他裏面的代碼的做用域鏈的最頂端變成 with
括號裏面的這個對象。做用域鏈是通過很複雜的狀況生成的結構,做用域鏈改了以後,系統內核會消耗大量的效率去更改做用域鏈,是會把程序變得很是慢的。因此 ES5
的嚴格模式爲了提升效率,禁用 with
語句。
以 0 開頭的八進制字面量過去常常會致使不少錯誤,在嚴格模式下,八進制字面量已經成爲無效的語法了。
(function(){
// 0 開頭就是八進制的標誌;
console.log(012);
})(); // 結果: 10 (自動轉化成十進制)
(function(){
"use strict"
console.log(012)
})(); //報錯:Uncaught SyntaxError: Octal literals are not allowed in strict mode.
複製代碼
parseInt()
的行爲。現在八進制的字面量在嚴格模式下會被看成以 0 開頭的十進制字面量。例如:(function(){
var value = 012;
console.log(value);
})(); // 結果: 10
(function(){
"use strict";
var value = parseInt("012");
console.log(value);
})(); // 結果: 12
複製代碼
若是對您有幫助,歡迎點贊關注;文章若有遺漏之處歡迎評論區留言討論。