詳解JavaScript嚴(yán)格模式

一、概述:

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ì)講解

  1. 所有的變量必須使用var 關(guān)鍵字聲明

  2. 不能使用delete關(guān)鍵字刪除全局變量 ,以前默認(rèn)刪除失敗,嚴(yán)格模式下直接報(bào)錯

  3. 在對象中不允許有同名的屬性

  4. 函數(shù)的參數(shù)必須唯一(不能出現(xiàn)同名的參數(shù))

  5. arguments對象的行為不同,在非嚴(yán)格模式下修改形參的值會反映到arguments中,而嚴(yán)格模式下則相對獨(dú)立

  6. 禁用了argument.calleecaller函數(shù),他們一個(gè)引用函數(shù)本身,一個(gè)引用調(diào)用函數(shù)

  7. 不能在if語句中聲明函數(shù)

  8. 禁止使用evalarguments作為標(biāo)識符(變量名)

  9. 禁止this指向全局對象

  10. 禁用了with語句

  11. 去掉了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對象的行為不同

說明:

  1. 在非嚴(yán)格模式下,修改了形參的值,arguments中的數(shù)據(jù)會跟著改變

  2. 嚴(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)錯
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)自:腳本之家 轉(zhuǎn)載 時(shí)間:2016-09-24我要評論 在 JavaScript 的嚴(yán)格模式下,對 JavaSc...
    Michael_林閱讀 443評論 1 1
  • 一、概述 除了正常運(yùn)行模式,ECMAscript 5添加了第二種運(yùn)行模式:"嚴(yán)格模式"(strict mode)。...
    Bruce_zhuan閱讀 394評論 0 6
  • 第5章 引用類型(返回首頁) 本章內(nèi)容 使用對象 創(chuàng)建并操作數(shù)組 理解基本的JavaScript類型 使用基本類型...
    大學(xué)一百閱讀 3,679評論 0 4
  • 這是一本非常歡笑中帶著眼淚的書,作者用輕松愉快的語調(diào)描述了少年時(shí)期與佐賀的阿嬤一起度過的貧窮歲月,因?yàn)楦赣H因核輻射...
    柯木木閱讀 1,284評論 0 5
  • 我想和你一起去看看海, 雖然我不高不帥而且還怕水 但我我還想和你一起去看看海, 讓夕陽的余暉細(xì)撒在你的發(fā)梢, 用雙...
    阿布Zz閱讀 298評論 0 0

友情鏈接更多精彩內(nèi)容