
一、概述:
JavaScript由于語法的不嚴(yán)謹(jǐn),一直所被人詬病。于是在ECMAscript 5添加了第二種運(yùn)行模式:“嚴(yán)格模式”。一旦使用嚴(yán)格模式,那么一些“不嚴(yán)謹(jǐn)”的語法代碼將不再被支持。
這樣做的好處是:
提早知道代碼中存在的錯誤,即使捕獲一些可能導(dǎo)致編程錯誤的ECMAScript行為。
提高編譯器效率,增加運(yùn)行速度;
為未來新版本的Javascript做好鋪墊。
二、使用方法
<script>//1
//在js代碼的頂部加上這么一句,聲明嚴(yán)格模式的使用
"use strict"; //注意:不能大寫
function testFun1 () {
//此處也為嚴(yán)格模式
}
</script>
<script> //2
//此作用域由于沒有聲明“嚴(yán)格模式”,因此此作用域的代碼按“非嚴(yán)格模式”編譯
str = "碼農(nóng)3號"; //不報(bào)錯
</script>
<script> //3
function testFun2 () {
"use strict"; //只對該函數(shù)作用域內(nèi)的代碼有效
}
//此處依然為"非嚴(yán)格模式"
</script>
注意:此處第一組script標(biāo)簽內(nèi)的代碼是使用了“嚴(yán)格模式”,而第二組script標(biāo)簽內(nèi)的代碼不是嚴(yán)格模式。因?yàn)槊恳唤Mscript標(biāo)簽就是一個(gè)作用域,而“嚴(yán)格模式”的聲明只對所在的作用域生效。
三、嚴(yán)格模式下的特點(diǎn)
顯式報(bào)錯
一些在正常模式下能正常運(yùn)行的代碼,在嚴(yán)格模式下會顯式報(bào)錯。比如正常模式下,對一個(gè)對象的只讀屬性進(jìn)行賦值,不會報(bào)錯,只會默默地失敗。嚴(yán)格模式下,將報(bào)錯。
"use strict";
var obj = {};
//該方法是給對象定義一個(gè)屬性,并設(shè)置它的一些“是否可操作”值
Object.defineProperty(o, "name", { value: "碼農(nóng)1號", writable: false });//將name屬性設(shè)置為只讀
obj.name = "大神"; // 報(bào)錯 (正常模式下只會默默賦值失敗)
創(chuàng)設(shè)eval作用域
正常模式下,Javascript語言有兩種變量作用域(scope):全局作用域和函數(shù)作用域。嚴(yán)格模式創(chuàng)設(shè)了第三種作用域:eval作用域。
正常模式下,eval語句的作用域,取決于它處于全局作用域,還是處于函數(shù)作用域。嚴(yán)格模式下,eval語句本身就是一個(gè)作用域,不再能夠生成全局變量了,它所生成的變量只能用于eval內(nèi)部。
"use strict";
var x = 2;
console.log(eval("var x = 5; x")); // 5
console.log(x); // 2
四、嚴(yán)格模式使用的注意點(diǎn)(不同點(diǎn))
對于使用的注意點(diǎn),本農(nóng)總結(jié)了11點(diǎn),此文將詳細(xì)講解
所有的變量必須使用var 關(guān)鍵字聲明
不能使用delete關(guān)鍵字刪除全局變量 ,以前默認(rèn)刪除失敗,嚴(yán)格模式下直接報(bào)錯
在對象中不允許有同名的屬性
函數(shù)的參數(shù)必須唯一(不能出現(xiàn)同名的參數(shù))
arguments對象的行為不同,在非嚴(yán)格模式下修改形參的值會反映到arguments中,而嚴(yán)格模式下則相對獨(dú)立
禁用了argument.callee和caller函數(shù),他們一個(gè)引用函數(shù)本身,一個(gè)引用調(diào)用函數(shù)
不能在if語句中聲明函數(shù)
禁止使用eval和arguments作為標(biāo)識符(變量名)
禁止this指向全局對象
禁用了with語句
去掉了JavaScript中的八進(jìn)制字面量(以0開頭的八進(jìn)制字面量是無效的語法)
針對以上注意點(diǎn),下面將講一一講解
1.所有的變量都必須使用var關(guān)鍵字聲明
非嚴(yán)格模式下:
a = 10;
console.log(a); //打印為:10
嚴(yán)格模式下:
"use strict";
a = 10; //這行直接報(bào)錯
console.log(a);
2.不能使用delete關(guān)鍵字刪除全局變量
非嚴(yán)格模式下:
//在“非嚴(yán)格模式”下,刪除失敗(靜默失敗),失敗了不吭聲,嚴(yán)格模式下會直接報(bào)錯
var a = 10;
var result = delete a;
console.log(result); //打印為:false;刪除失敗,var聲明的變量無法delete關(guān)鍵刪除
console.log(a); //打印為:10
嚴(yán)格模式下:
"use strict";
var a = 10;
var result = delete a; //這行直接報(bào)錯
3.在對象中不允許有同名的屬性
嚴(yán)格模式下:
var obj = {
name:"碼農(nóng)1號",
name:"碼農(nóng)2號"
}
console.log(obj.name); //打印為:碼農(nóng)2號;相當(dāng)于執(zhí)行了obj.name = "碼農(nóng)1號";obj.name = "碼農(nóng)2號";
非嚴(yán)格模式下:
"use strict";
var obj = {
name:"碼農(nóng)1號",
name:"碼農(nóng)2號"
}; //直接報(bào)錯
4.函數(shù)的參數(shù)必須唯一(不能出現(xiàn)同名的參數(shù))
在非嚴(yán)格模式下,如果函數(shù)在定義的時(shí)候,使用了多個(gè)同名的形參,則在函數(shù)內(nèi)部形參的實(shí)際值為最后一個(gè)傳入的實(shí)參值
在嚴(yán)格模式下,直接報(bào)錯
非嚴(yán)格模式下
function foo(a, b, a) {
console.log(a);
}
foo(1, 2, 3); //打印為:3
? 非嚴(yán)格模式下:
"use strict";
function foo(a, b, c) {
console.log(a);
} //該函數(shù)的聲明將直接報(bào)錯
5.函數(shù)內(nèi)的arguments對象的行為不同
說明:
在非嚴(yán)格模式下,修改了形參的值,arguments中的數(shù)據(jù)會跟著改變
嚴(yán)格模式下,在函數(shù)內(nèi)部修改了對象的指向,對arguments的值不會產(chǎn)生影響。因?yàn)樵趪?yán)格模式下,形參的值和arguments的值是相互獨(dú)立的,在函數(shù)內(nèi)部修改了形參的值對arguments不受影響
先來看看非嚴(yán)格模式下,arguments與形參的關(guān)系:
//測試引用類型(對象類型)的值作為函數(shù)的參數(shù)
function funcName(obj) {
console.log(obj); //執(zhí)行后打印為:{name:"碼農(nóng)一號"}
console.log(arguments[0]);//打印為:{name:"碼農(nóng)一號"}
//在函數(shù)內(nèi)部修改形參的值
obj = {age:20}; //修改形參
console.log(obj); //打印為:{age:20}
console.log(arguments[0]); //打印為:{age:20}
}
funcName({name:"碼農(nóng)一號"});
//測試基本類型數(shù)據(jù)作為函數(shù)的參數(shù)
function fun(str) {
console.log(str);
console.log(arguments[0]); //上下打印都為:"hi";
str = "hello"; //修改形參
console.log(arguments[0]); //打印為:"hello"
}
fun("hi");
結(jié)論:非嚴(yán)格模式下,修改形參的值,arguments內(nèi)的元素會跟著改變!
下面再來驗(yàn)證下嚴(yán)格模式下,形參與arguments的關(guān)系:
//聲明嚴(yán)格模式
"use script";
//測試引用類型(對象類型)的值作為函數(shù)的參數(shù)
function funcName(obj) {
console.log(obj); //執(zhí)行后打印為:{name:"碼農(nóng)一號"}
console.log(arguments[0]);//打印為:{name:"碼農(nóng)一號"}
//在函數(shù)內(nèi)部修改形參的值
obj = {age:20}; //修改形參
console.log(obj); //打印為:{age:20}
console.log(arguments[0]); //打印為:{name:"碼農(nóng)一號"}
}
funcName({name:"碼農(nóng)一號"});
//測試基本類型數(shù)據(jù)作為函數(shù)的參數(shù)
function fun(str) {
console.log(str);
console.log(arguments[0]); //上下打印都為:"hi";
str = "hello"; //修改形參
console.log(arguments[0]); //打印為:"hi" ,str的修改不影響arguments
}
fun("hi");
結(jié)論:嚴(yán)格模式下,形參和arguments關(guān)系相互獨(dú)立,各不影響**
6.禁用了arguments.callee和caller函數(shù)
說明:
? arguments.callee 是對函數(shù)自身的引用,fun.calller 是對調(diào)用函數(shù)的引用
//1.arguments.callee指向函數(shù)自身,callee常用于遞歸函數(shù)
function testFun() {
console.log(arguments.callee === testFun); //true
}
testFun();
//2.caller是對調(diào)用自己的函數(shù)的引用,以下例子展示了caller的使用
function fun1() {
//這里可以使用fun1.caller,也可以使用arguments.callee.caller。兩者等價(jià)
console.log(arguments.callee.caller); //這里打印為:fun2(){ fun1(); }
}
function fun2() {
fun1();
}
fun2();
而在 嚴(yán)格模式 下,這兩個(gè)方法不能使用,否則程序報(bào)錯。
7.不能在if語句中聲明函數(shù)
非嚴(yán)格模式下:
//如果在if語句中聲明函數(shù),則會產(chǎn)生語法錯誤
if (true) {
function demo() {
console.log("我是碼農(nóng)");
}
}
demo(); //打印為:"我是碼農(nóng)";非嚴(yán)格模式下,可以正常調(diào)用
嚴(yán)格模式下:
"use strict";
//如果在if語句中聲明函數(shù),則會產(chǎn)生語法錯誤
if (true) {
function demo() { //此處報(bào)錯
console.log("我是碼農(nóng)");
}
}
8.禁止使用eval和arguments作為標(biāo)識符
//非嚴(yán)格模式下,兩者均可被當(dāng)做 變量名 使用
var eval = "碼農(nóng)1號";
var arguments = "碼農(nóng)2號"
console.log(eval); //輸出結(jié)果:"碼農(nóng)1號"
console.log(arguments); //輸出結(jié)果:"碼農(nóng)2號"
//嚴(yán)格模式下,兩者不能被當(dāng)做變量名
"use strict";
var eval = "碼農(nóng)1號"; //直接報(bào)錯,arguments同理
9.禁止this指向全局對象
在嚴(yán)格模式下,函數(shù)this的值始終是指定的值,無論指定的是什么值
var name = "測試的name";
function demoTest()
//在非嚴(yán)格模式下,打印出來的this為全局的對象window!在嚴(yán)格模式下打印出來的this為undefined
console.log(this);
}
demoTest();
10.禁用了with語句
下面為with的使用介紹,但是再嚴(yán)格模式下將不再支持該方法,調(diào)用會顯示報(bào)錯
var o = {name:"碼農(nóng)x號",age:22};
with(o) {
name = "kevin";
age = 48
}
console.log(o); //輸出結(jié)果:{name:"kevin",age:48}
11.禁用了八進(jìn)制
//以0開頭的數(shù)據(jù)為八進(jìn)制
var num = 023;
console.log(num); //輸出結(jié)果:19
嚴(yán)格模式下:
"use strict";
var num = 023; //顯式報(bào)錯