嚴格模式
1化借、設(shè)立嚴格模式的目的
- 消除JavaScript語法的一些不合理潜慎、不嚴謹之處,減少一些怪異行為蓖康;(會將JavaScript陷阱直接變成明顯錯誤铐炫,靜默失敗)
- 消除代碼運行的一些不安全之處,保證代碼運行的安全蒜焊;(修正了一些引擎難以優(yōu)化的錯誤)
- 提高編譯器的效率倒信,增加運行速度;
- 為未來新版本的JavaScript做好鋪墊泳梆。
2鳖悠、瀏覽器支持情況
IE10+榜掌、Firefox4+、Safari5.1+乘综、Chrome
3憎账、嚴格模式標志
"use strict";
注:老版本的瀏覽器,如不支持嚴格模式卡辰,會將其當(dāng)做一行普通字符串忽略胞皱。
4、嚴格模式的使用
- 如果'use strict'放在js文件首行九妈,則整個js文件都將以"嚴格模式"運行反砌;(如果該句不在首行,則無效)允蚣,需要特別注意:多個文件合并成一個文件的情況,此情況下呆贿,提供一個方法嚷兔,每個文件使用匿名函數(shù)自執(zhí)行,將'use strict'放在函數(shù)首行做入;
- 將'use strict'放在函數(shù)第一行冒晰,表示整個函數(shù)為'嚴格模式',函數(shù)以外在為正常模式竟块;
5壶运、嚴格模式的一些改變
變量的聲明---嚴格模式下,如果變量沒有聲明就賦值會報錯浪秘;
<pre>
'use strict';
v = 1; //報錯蒋情,v未聲明
for(i = 0; i < 2; i++){} //報錯,i未聲明
</pre>
禁止使用with語句:因為with語句無法再編譯時就確定耸携,屬性到底歸屬哪個對象
首先棵癣,嚴格模式禁用with,with所引起的問題是快內(nèi)的任何名稱可以映射(map)到with傳進來的對象的屬性夺衍,也可以映射到包圍這個塊的作用域內(nèi)的變量(甚至是全局變量)狈谊,這一切都是在運行時決定的;在代碼運行之前是無法得知的沟沙,嚴格模式下河劝,使用with會引起語法錯誤,所以就不會存在with塊內(nèi)的變量在運行時才決定引用到哪里的情況了矛紫。
<pre>
'use strict';
var x = 17;
with(obj){ // 語法錯誤 Uncaught SyntaxError: Strict mode code may not include a with statement
v; //如果沒有開啟嚴格模式赎瞎,with中的這個this指向上面的那個x,還是obj.x颊咬?
//如果不運行代碼煎娇,我們無法知道二庵,因此,這種代碼讓引擎無法進行優(yōu)化缓呛,速度也就會變慢催享。
}
</pre>
創(chuàng)設(shè)eval作用域
正常模式下,JavaScript語言有兩種變量作用域(scope):全局作用域和函數(shù)作用域哟绊。嚴格模式創(chuàng)設(shè)了第三種作用域:eval作用域因妙。
正常模式下,eval語句的作用域票髓,取決于他處于全局作用域攀涵,還是處于函數(shù)作用域。嚴格模式下洽沟,eval語句本身就是一個作用域以故,不再能夠生成全局變量了,他所生成的變量只能用于eval內(nèi)部裆操。
<pre>
'use strcit';
var x = 2;
console.info(eval("var x = 1; x")); // 1
console.info(x); // 2 正常模式下此值為 1
</pre>
this關(guān)鍵字指向
<pre>
function f(){
console.log(this) //window
}
function f(){
'use strict';
console.log(this) //undefined
}
//因此在使用構(gòu)造函數(shù)時怒详,如果沒有實例化new,this不再指向全局對象踪区,而是報錯
</pre>
在嚴格模式下昆烁,如果使用call()改變this指針的上下文,如果傳入一個原始值缎岗,則會轉(zhuǎn)換為一個對象静尼;在嚴格模式下,則直接返回原始值传泊;
<pre>
console.log(function(){
return this; //Number {[[PrimitiveValue]]: 1}
}.call(1))
console.log(function(){
'use strict';
return this; // 1
}.call(1))
</pre>
禁止在函數(shù)內(nèi)部遍歷調(diào)用棧
<pre>
function f(){
'use strict';
f.caller; //報錯鼠渺;
f.arguments; //報錯;
//Uncaught TypeError: 'caller' and 'arguments' are restricted function properties and cannot be accessed in this context.
}
</pre>
禁止隨意刪除變量
<pre>
'use strict';
var x;
delete x; // 語法報錯
eval('var y; delete y;') //語法報錯
// 正常模式下:delete是無法刪除va聲明出的變量的眷细,不過通過eval聲明的變量系冗,可以被正常刪除
var o = Object.create(null,{'x':{
value : 1,
configurable : true
}});
delete o.x; //刪除成功
</pre>
對一個對象的只讀屬性賦值會報錯
<pre>
// 正常模式下不會報錯
'use strict';
var o = {};
Object.defineProperty(o,'v',{
value : 1,
writable : false
});
o.v = 2; // 報錯;useStrict.html:50 Uncaught TypeError: Cannot assign to read only property "v" of object
</pre>
對一個使用getter方法讀取的屬性賦值會報錯
<pre>
'use strict';
var o = {
get v() {return 1;}
};
o.v = 2; // 報錯薪鹦;
</pre>
對禁止擴展的對象添加新屬性掌敬,會報錯
<pre>
'use strict';
var o = {};
Object.preventExtensions(o);
o.v = 1; // 報錯
</pre>
刪除一個不可刪除的屬性,報錯
<pre>
'use strict';
delete Object.pretotype; //報錯池磁;
</pre>
對象不能有重名的屬性(正常模式是覆蓋奔害,嚴格模式報錯)(此問題測試無結(jié)果,據(jù)說已經(jīng)修正)
函數(shù)不能有重名的參數(shù)(正常模式下可以通過arguments可以讀取地熄,嚴格模式報錯)
禁止八進制表示法
- 正常模式下华临,整數(shù)的第一位為0表示這是八進制數(shù)
- 但是在嚴格模式下這種寫法會報錯
- ps: parseInt(010) 正常模式下是8,但是嚴格模式不允許使用0開頭的數(shù)字端考,所以此處如果改成 parseInt('010'),結(jié)果就不對了
arguments對象的限制
<pre>
'use strict';
arguments++; //報錯
var obj = {set p(arguments){}}; //報錯
try {} catch(arguments){}; //報錯
function arguments(){}; //報錯
var f = new Function('arguments',"'use strcit'; return 1;");//報錯
</pre>
arguments不再追蹤參數(shù)的變化
<pre>
function f(a){
'use strict';
a = 2;
return [a,arguments[0]];
}
f(1); // [2,1] 正常模式下為[2,2]
</pre>
禁止使用arguments.callee,arguments.caller
無法通過arguments.callee匿名函數(shù)自調(diào)用,也不能通過arguments.caller來獲取調(diào)用函數(shù)
函數(shù)必須聲明在頂層(暫時未測試出來結(jié)果)
<pre>
//以下代碼雅潭,是MDN實例揭厚,但是自測未發(fā)現(xiàn)報錯
"use strict";
if (true){
function f() { } // !!! 語法錯誤
f();
}
for (var i = 0; i < 5; i++){
function f2() { } // !!! 語法錯誤
f2();
}
function baz() { // 合法
function eit() { } // 同樣合法
}
</pre>
保留字
嚴格模式新智能了一些保留字,使用這些詞作為變量名將會報錯
implements,interface,let,package,private,protected,public,static,yield,class,enum,export,extends,import,super,const
JavaScript語法檢測工具jshint
1扶供、安裝
在node環(huán)境下筛圆,全局安裝jshint
npm install jshint -g
2、使用方法
- 單獨對js文件進行檢測:在該文件目錄下
jshint xxx.js
- 檢測當(dāng)前目錄及其子目錄所有js文件的語法
jshint ./
3椿浓、配置文件
- 使用-config選項制定配置文件:jshint -config ./xxx ./ 表示檢測當(dāng)前目錄內(nèi)所有的js文件太援,并指定配置文件為當(dāng)前目錄下的xxx文件。
- 使用.jshintrc文件扳碍,如果在運行jshint時提岔,沒有-config選項,則會以當(dāng)前目錄的.jshintrc文件為配置文件笋敞,如果當(dāng)前目錄沒有這個文件碱蒙,則以其父目錄.jshintrc文件為配置文件,仍沒有的話夯巷,則繼續(xù)找其父目錄赛惩,直至根目錄。
- 在nodejs項目的package.json文件的jshintConfig字段中設(shè)置配置文件鞭莽。
- 還可以在需檢測的js文件內(nèi)配置選項
/* jshint undef:true,unused:true /* /* global Global */
或者//jshint undef:true,unused:true
這兩種方式都可以坊秸,如果只把這些注釋寫在某個函數(shù)內(nèi)麸祷,則改配置只在函數(shù)內(nèi)起作用澎怒。 - 有時候我們不希望檢查一些文件(比如一些庫),可以建一個.jshintignore文件阶牍,把需要忽略的文件名寫在里面喷面,支持通配符。
4走孽、配置選項
- asi ----- 如果是真惧辈,JSHint會無視沒有加分號的行尾
- bitwise -----如果為真,JSHint會禁用位運算符 (ps:Javascript允許位運算磕瓷,但是他卻沒有整型盒齿,位運算符要把參與運算的數(shù)字從浮點數(shù)變?yōu)檎麛?shù),并在運算后再轉(zhuǎn)換回來困食。這樣他們的效率就不如在別的語言中那么高)
- boss -----如果為真边翁,那么JSHint會允許在if,for硕盹,while里面編寫賦值語句 (ps:一般來說符匾,我們會在循環(huán)、判斷等語句中加入值的比較來做語句的運行條件瘩例,有時候會把==錯寫成賦值的=啊胶,通常甸各,JSHint會把這個認定為一個錯誤,但是開啟這個選項的化焰坪,JSHint就不會檢查判斷條件中的賦值 )
- curly ----- 如果為真趣倾,JSHint會要求你在使用if和while等結(jié)構(gòu)語句時加上{}來明確代碼塊
- debug ----- 如果為真,JSHint會允許代碼中出現(xiàn)debugger的語句琳彩。不過建議你最好在檢測代碼前去掉debug的語句
- eqeqeq ----- 如果為真誊酌,JSHint會看你在代碼中是否都用了===或者是!==,而不是使用==和!=(ps:我們建議你在比較0露乏,”(空字符)碧浊,undefined,null瘟仿,false和true的時候使用===和!===)
- eqnull ----- 如果為真箱锐,JSHint會允許使用”== null”作比較(ps:== null 通常用來判斷一個變量是undefined或者是null(當(dāng)時用==,null和undefined都會轉(zhuǎn)化為false)
- evil ----- 如果為真劳较,JSHint會允許使用eval(ps:eval提供了訪問Javascript編譯器的途徑驹止,這有時很有用,但是同時也對你的代碼形成了注入攻擊的危險观蜗,并且會對debug造成一些困難臊恋,F(xiàn)unction構(gòu)造函數(shù)也是另一個‘eval’,另外墓捻,當(dāng)傳入的參數(shù)是字符串的時候抖仅,setTimeout和setInterval也會類似于eval)
- forin -----如果為真,那么砖第,JSHint允許在for in 循環(huán)里面不出現(xiàn)hasOwnProperty(ps:for in循環(huán)一般用來遍歷一個對象的屬性撤卢,這其中也包括他繼承自原型鏈的屬性,而hasOwnProperty可以來判斷一個屬性是否是對象本身的屬性而不是繼承得來的)
- immed -----如果為真梧兼,JSHint要求匿名函數(shù)的調(diào)用如下(ps:
(function(){ // }()); 而不是 (function(){ //bla bla })();
) - laxbreak -----如果為真放吩,JSHint則不會檢查換行(ps:Javascript會通過自動補充分號來修正一些錯誤,因此這個選項可以檢查一些潛在的問題)
- maxerr ----- 設(shè)定錯誤的閾值羽杰,超過這個閾值jshint不再向下檢查渡紫,提示錯誤太多
- newcap -----如果為真,JSHint會要求每一個構(gòu)造函數(shù)名都要大寫字母開頭
- noarg -----如果為真考赛,JSHint會禁止arguments.caller和arguments.callee的使用
- noempty -----如果為真惕澎,JSHint會禁止出現(xiàn)空的代碼塊,即沒有語句的代碼塊
- nomen -----如果為真欲虚,JSHint會禁用下劃線的變量名
- onevar -----如果為真集灌,JSHint期望函數(shù)只被var的形式聲明一遍
- passfail -----如果為真,JSHint會在發(fā)現(xiàn)首個錯誤后停止檢查
- plusplus -----如果為真,JSHint會禁用自增運算和自減運算(ps:++和--可能會帶來一些代碼的閱讀困惑)
- regexp -----如果為真欣喧,JSHint會不允許使用.和[^…]的正則(ps:因為這樣的正則往往會匹配到你不期望的內(nèi)容腌零,并可能會應(yīng)用造成一些危害)
- undef -----如果為真,JSHint會要求所有的非全局變量唆阿,在使用前都被聲明(ps:如果你不在一個本地作用域內(nèi)使用var的方式來聲明變量益涧,Javascript會把它放到全局作用域下面。這樣會很容易引起錯誤)
- sub -----如果為真驯鳖,JSHint會允許各種形式的下標來訪問對象(ps:通常闲询,JSHint希望你只是用點運算符來讀取對象的屬性(除非這個屬性名是一個保留字),如果你不希望這樣可以關(guān)閉這個選項)
- strict -----如果為真浅辙,JSHint會要求你使用use strict;語法
- white -----如果為true扭弧,JSHint會依據(jù)嚴格的空白規(guī)范檢查你的代碼
- Environments -----你的代碼所在的環(huán)境
如需轉(zhuǎn)載,請注明出處记舆!