在閱讀jQuery源碼的時候,發現jQuery用到的是'use strict'嚴格模式。所以就去查閱了一些資料來補充本身對嚴格模式的認識。下面是參考【javascript高級程序設計(第三版)】的內容。javascript
‘嚴格模式’最先引入是ECMAScript5。經過嚴格模式,能夠在函數內部選擇進行較爲嚴格的全局或局部的錯誤條件檢測。
html
❝【補充】ECMAScript各版本的劃分,推薦:阮一峯老師中ECMAScript的歷史介紹java
❞
能夠提前知道代碼中存在的錯誤,及早捕獲一些可能致使編程錯誤的ECMAScript行爲。es6
理解嚴格模式的規則很是重要,支持嚴格模式的瀏覽器有web
當咱們想要讓本身編寫的代碼處在嚴格模式的時候,可使用嚴格模式的編譯指示(pragma),也就是一個不會賦給任何變量的字符串:'use strict'
。「這就話須要放在想要處於嚴格模式的首句。」編程
這種語法能夠向後兼容那些不支持嚴格模式的javascript引擎。瀏覽器
若是在全局做用域中給出的這個編譯指示,則整個腳本都將使用嚴格模式。也就是這個編譯指示放在哪裏,只要有javascript代碼,就會讓其處於嚴格模式。安全
在函數中使用嚴格模式。把'use strict'放在首位,就能夠對整個函數其做用app
function fn(){
'use strict'
//要實現的代碼
}
複製代碼
❝【補充】字面量: 百度百科的解釋
❞
通俗理解:let a = 1;
這個等號左邊的叫作變量,等號右邊的就叫作字面量編輯器
在嚴格模式下,何時建立變量以及怎麼建立變量都是有限制的。
未聲明變量在「嚴格模式」與「非嚴格模式」下的區別:
message
前面沒有
var
關鍵字,也沒有定義爲全局對象的屬性;也能夠將它建立爲全局變量
ReferenceError
這個錯誤
message = 'Hello World!'
console.log(window.message) //'Hello World!'
複製代碼
'use strict'
message = 'Hello World!'
console.log(window.message); //Uncaught ReferenceError: message2 is not defined
複製代碼
delete
刪除元素,但會靜態默認失敗(也就是刪除不了,可是不會報錯,哈哈)
var color = 'red';
delete color;
console.log(color); //'red'
複製代碼
'use strict'
var color = 'red';
delete color;
console.log(color); //Uncaught SyntaxError: Delete of an unqualified identifier in strict mode.
複製代碼
不能使用 implements
、interface
、let
、package
、 private
、protected
、public
、static
和 yield
做爲變量名。這些都是保留字,未來的 ECMAScript 版本中可能會用到它們。
var implements=1;
console.log(implements); //1
複製代碼
'use strict'
var implements=1;
console.log(implements);//Uncaught SyntaxError: Unexpected strict mode reserved word
複製代碼
在嚴格模式下操做對象比在非嚴格模式下更容易致使錯誤。
所以,在開發中使用嚴格模式會加大早發現錯誤的可能性。
TypeError
;
delete
操做符會拋出
TypeError
;
TypeError
。
"use strict";
// 給不可寫屬性賦值
var obj1 = {};
Object.defineProperty(obj1, "x", { value: 42, writable: false });
obj1.x = 9; // 拋出TypeError錯誤
// 給只讀屬性賦值
var obj2 = { get x() { return 17; } };
obj2.x = 5; // 拋出TypeError錯誤
// 給不可擴展對象的新屬性賦值
var fixed = {};
Object.preventExtensions(fixed);
fixed.newProp = "ohai"; // 拋出TypeError錯誤
複製代碼
「這個問題在ECMAScript6中已經不復存在,也就是使用嚴格模式時,和非嚴格模式同樣,都是最後那個值,不會報錯」
"use strict";
var person = {
name: "Nicholas",
name: "Greg"
};
複製代碼
這裏的對象 person 有兩個屬性,都叫 name。在非嚴格模式下,person 對象的 name 屬性值是第二個,而在嚴格模式下,這樣的代碼會致使語法錯誤。
function sum(num,num){
//函數體
return num + num; // 要想訪問第一個參數:return arguments[0] + num;
}
console.log(sum(10,20)); // 40
複製代碼
'use strict';
function sum(num,num){
//函數體
return num + num;
}
console.log(sum(10,20)); // Uncaught SyntaxError: Duplicate parameter name not allowed in this context
複製代碼
arguments
中
arguments
中
function sum(num){
num=20;
console.log(arguments[0]); //20
console.log(num); //20
}
sum(10);
複製代碼
'use strict';
function sum(num){
num=20;
console.log(arguments[0]); //10
console.log(num); //20
}
sum(10);
複製代碼
以上代碼中,函數sum()只有一個命名參數 num。調用這個函數時傳入了一個參數10, 這個值賦給了num。而在函數內部,num被改成20。在非嚴格模式下,這個修改也會改變 arguments[0]的值,但在嚴格模式下,arguments[0]的值仍然是傳入的值。
function factorial(num) {
if (num <= 1) {
return 1;
} else {
return num * arguments.callee(num - 1)
}
}
var result = factorial(5);
console.log(result); //120 =>5*4*3*2*1
複製代碼
'use strict';
function factorial(num) {
if (num <= 1) {
return 1;
} else {
return num * arguments.callee(num - 1)
}
}
var result = factorial(5);
console.log(result); //120 =>5*4*3*2*1
複製代碼
【補充】arguments.callee
是已經被廢棄的,屬性用在函數執行的時候調用自身(能夠理解爲遞歸的思想)。雖然arguments.caller
已經不可以使用了,可是你還可使用 Function.caller
。
與變量相似,嚴格模式對函數名也作出了限制,不容許用 implements
、interface
、let
、package
、private
、protected
、public
、static
和 yield
做爲函數名。
if / for
語句外部
if (true) {
function f() { console.log(1); }
}
f(); //函數執行輸出1
for (var i = 0; i < 5; i++) {
function f2() {console.log(1); }
f2(); //輸出5次1
}
f2(); //輸出1
複製代碼
"use strict";
if (true) {
function f() { console.log(1); }
}
f(); //Uncaught ReferenceError: f is not defined at
for (var i = 0; i < 5; i++) {
function f2() {console.log(1); }
f2(); //輸出5次1
}
f2(); //Uncaught ReferenceError: f2 is not defined at
複製代碼
飽受詬病的 eval()
函數在嚴格模式下也獲得了提高。最大的變化就是它在包含上下文中再也不建立變量或函數。
function doSomething(){
eval("var x=10");
alert(x);
}
doSomething(); //函數執行會彈出10
複製代碼
'use strict';
function doSomething(){
eval("var x=10");
alert(x);
}
doSomething(); //函數執行報錯:Uncaught ReferenceError: x is not defined at doSomething
複製代碼
若是是在非嚴格模式下,以上代碼會在函數 doSomething()
中建立一個局部變量 x
,而後 alert()
還會顯示該變量的值。但在嚴格模式下,在 doSomething()
函數中調用 eval()
不會建立變量 x
,所以調用 alert()
會致使拋出 ReferenceError
,由於 x
沒有定義。
能夠在 eval()中聲明變量和函數,但這些變量或函數只能在被求值的特殊做用域中有效,隨後就將被銷燬。所以,如下代碼能夠運行,沒有問題:
"use strict";
var result = eval("var x=10, y=11; x+y");
alert(result); //21
複製代碼
這裏在 eval()
中聲明瞭變量 x
和y
,而後將它們加在一塊兒,返回了它們的和。因而,result
變量的值是 21,即 x
和y
相加的結果。而在調用alert()
時,儘管 x
和 y
已經不存在了,result
變量的值仍然是有效的。
嚴格模式已經明確禁止使用eval
和 arguments
做爲標識符,也不容許讀寫它們的值。
var eval = 10;
var arguments = "Hello world!";
console.log(eval,arguments); //10 "Hello world!"
複製代碼
'use strict'
var eval = 10;
var arguments = "Hello world!";
console.log(eval,arguments); //Uncaught SyntaxError: Unexpected eval or arguments in strict mode
複製代碼
JavaScript 中一個最大的安全問題,也是最容易讓人迷茫的地方,就是在某些狀況下如何抑制 this的值。
var color = "red";
function displayColor() {
console.log(this.color);
}
displayColor.call(null); //'red'
複製代碼
'use strict';
var color = "red";
function displayColor() {
console.log(this.color);
}
displayColor.call(null); //Uncaught TypeError: Cannot read property 'color' of null at displayColor
複製代碼
以上代碼向displayColor.call()
中傳入了null
,若是在是非嚴格模式下,這意味着函數的this
值是全局對象。結果就是輸出"red"
。而在嚴格模式下,這個函數的 this
的值是 null
,所以在訪問 null
的屬性時就會拋出錯誤。
首先是拋棄了 with 語句。
with (location) {
console.log(href);//http://127.0.0.1:5501/%E7%AC%AC%E5%85%AD%E5%91%A8/%E7%AC%AC%E4%BA%8C%E5%A4%A9/%E4%B8%A5%E6%A0%BC%E6%A8%A1%E5%BC%8F.html
}
複製代碼
'use strict'
with (location) {
console.log(href); //Uncaught SyntaxError: Strict mode code may not include a with statement
}
複製代碼
所以,在嚴格模式下使用 with會致使語法錯誤
var value = 010;
console.log(value);//8
複製代碼
'use strict'
var value = 010;
console.log(value);//Uncaught SyntaxError: Octal literals are not allowed in strict mode.
複製代碼
本文參考了《javascript高級程序設計(第三版)》 以及 MDN網站。把內容進行了總結,每個的不一樣都使用代碼的形式展現了出來,但願對廣大朋友們有幫助。若是感受本文不錯,能夠點贊支持一下。能夠關注一下