理解javascript中的嚴(yán)格模式
一、什么是嚴(yán)格模式
我們平時(shí)寫的JavaScript代碼一般都運(yùn)行在正常模式中的,除了正常運(yùn)行模式,ECMAscript 5添加了第二種運(yùn)行模式:”嚴(yán)格模式”(strict mode)??疵志椭?,這種模式會(huì)讓JavaScript在更嚴(yán)格的環(huán)境中運(yùn)行。
包括IE 10在內(nèi)的主流瀏覽器,都已經(jīng)支持它,許多大項(xiàng)目已經(jīng)開始全面擁抱。(github上面好多項(xiàng)目都是用的嚴(yán)格模式)
二、啟用嚴(yán)格模式
為整個(gè)腳本啟用嚴(yán)格模式
在所有語句之前放一個(gè)特定語句 "use strict";
假設(shè)有一個(gè)腳本reeoo.js,可以這樣開啟嚴(yán)格模式:
"use strict"; var name = "Reeoo"; console.log(name);
BUT這種寫法存在天然的坑,假如我們要做代碼合并,我現(xiàn)在要把heigui.js:
heigui = "db";
和reeoo.js進(jìn)行合并,本來兩個(gè)腳本分開執(zhí)行是好好的,合起來就會(huì)報(bào)錯(cuò)。
Uncaught ReferenceError: heigui is not defined(…)
一個(gè)嚴(yán)格模式的腳本和一個(gè)非嚴(yán)格模式的腳本合并可能會(huì)導(dǎo)致非嚴(yán)格模式的腳本代碼報(bào)錯(cuò),建議代碼都包在一個(gè)立即執(zhí)行函數(shù)里面。
(function(){ "use strict"; var name = "reeoo"; })(); (function(){ heigui = "db"; })();
這樣合并之后就不會(huì)報(bào)錯(cuò)了。
為某個(gè)函數(shù)啟用嚴(yán)格模式
要給某個(gè)函數(shù)開啟嚴(yán)格模式,得把"use strict"; 聲明放在函數(shù)體所有語句之前就行了。
function strictFun() { // 函數(shù)級別嚴(yán)格模式語法 'use strict'; console.log('I am a strictmode function!'); } function normalFun() { console.log('I am a mormal function!'); }
Chrome中調(diào)試嚴(yán)格模式
我有這么一段代碼:
'use strict' name = "reeoo"; console.log(name)
把這段代碼直接粘貼到Chrome的控制臺中執(zhí)行,正常情況下應(yīng)該報(bào)錯(cuò),但是并沒有報(bào)錯(cuò),
很顯然,嚴(yán)格模式下變量不適用var聲明是不合法的,但是為什么沒有報(bào)錯(cuò)?
這是什么鬼,難道Chrome不支持嚴(yán)格模式?開什么玩笑。。。
網(wǎng)上搜了一下,原來Chrome的控制臺的代碼是運(yùn)行在eval之中的,你沒法對eval函數(shù)使用嚴(yán)格模式(應(yīng)該也不完全對,但是具體Chrome做了什么,不得而知),下圖說明eval函數(shù)可以使用嚴(yán)格模式:
要想在Chrome瀏覽器中對嚴(yán)格模式正常報(bào)錯(cuò),需要在代碼外層套一個(gè)立即執(zhí)行函數(shù),或者其它類似的措施。
(function(){ 'use strict' name = "reeoo"; console.log(name) })()
這樣就可以了
FireFox代碼草稿紙調(diào)試嚴(yán)格模式
Chrome非要我們包一層閉包才能跑嚴(yán)格模式,既然這么麻煩,有沒有別的方式可以直接跑嚴(yán)格模式的代碼呢?
FireFox有一個(gè)代碼草稿紙可以直接跑,快捷鍵SHIFT+F4
嚴(yán)格模式到底有多嚴(yán)格
嚴(yán)格模式中一些重要的限制
1、變量聲明
不允許使用一個(gè)沒有聲明的變量
"use strict"; name = "reeoo";
報(bào)錯(cuò)(代碼草稿紙,下同)
Exception: ReferenceError: assignment to undeclared variable name
2、修改只讀屬性的值
"use strict"; var testObj = Object.defineProperties({}, { prop1: { value: 10, writable: false // 一個(gè)只讀的屬性 }, prop2: { get: function () { } } }); testObj.prop1 = 20; //嘗試改變prop1的值 testObj.prop2 = 30;//嘗試改變prop2的值
嚴(yán)格模式下會(huì)報(bào)錯(cuò):
Uncaught TypeError: Cannot assign to read only property 'prop1' of #<Object>
非嚴(yán)格模式頂多就是值賦不上去而已,并不會(huì)報(bào)錯(cuò)
3、修改不可擴(kuò)展的屬性
表現(xiàn)為將屬性添加到 extensible 屬性設(shè)置為 false 的對象。
"use strict"; var testObj = new Object(); Object.preventExtensions(testObj);//經(jīng)過這個(gè)方法處理過的對象,不影響原有對象的刪除,修改.但是無法添加新的屬性成員了. testObj.name = "reeoo";
嚴(yán)格模式報(bào)錯(cuò):
Uncaught TypeError: Can't add property name, object is not extensible
非嚴(yán)格模式不會(huì)報(bào)錯(cuò),但是testObj也不會(huì)被擴(kuò)展。
4、刪除變量、函數(shù)或參數(shù)
刪除 configurable 特性設(shè)置為 false 的屬性。
"use strict"; var testvar = 15,testObj={}; function testFunc() {}; delete testvar; delete testFunc; Object.defineProperty(testObj, "testvar", { value: 10, configurable: false }); delete testObj.testvar;
報(bào)錯(cuò):
Uncaught SyntaxError: Delete of an unqualified identifier in strict mode.
5、在一個(gè)對象文本中多次定義某個(gè)屬性
嚴(yán)格模式下不允許一個(gè)屬性有多個(gè)定義
"use strict"; var testObj = { prop1: 10, prop2: 15, prop1: 20 };
報(bào)錯(cuò)(node控制臺)
Duplicate data property in object literal not allowed in strict mode
正常模式中后聲明的重復(fù)的變量會(huì)覆蓋前面聲明的,而且不會(huì)報(bào)錯(cuò)。
注:這個(gè)問題在ECMAScript6中已被修復(fù)。
6、嚴(yán)格模式下不允許形參參數(shù)名稱重復(fù)
"use strict"; function testFunc(param1, param1) { return 1; };
報(bào)錯(cuò):
Uncaught SyntaxError: Duplicate parameter name not allowed in this context
7、無法使用標(biāo)識符的未來保留字。嚴(yán)格模式下將保留標(biāo)識符名稱
一下標(biāo)識符(ES6中依然沒有實(shí)現(xiàn)的)在嚴(yán)格模式中是不能使用的,否則也會(huì)報(bào)錯(cuò)。
用了就是這個(gè)下場:
Uncaught SyntaxError: Unexpected strict mode reserved word
- implements
- interface
- package
- private
- protected
- public
- static
- yield
8、嚴(yán)格模式下不允許使用八進(jìn)制數(shù)字參數(shù)和轉(zhuǎn)義字符
"use strict"; var testoctal = 010; var testescape = \010;
報(bào)錯(cuò):
Uncaught SyntaxError: Unexpected token ILLEGAL(…)
9、當(dāng)this 的值為 null 或 undefined 時(shí),該值不會(huì)轉(zhuǎn)換為全局對象
比如:
"use strict"; function testFunc() { return this; } var testvar = testFunc();
在非嚴(yán)格模式下,testvar 的值為全局對象window,但在嚴(yán)格模式下,該值為 undefined。
10、字符串"eval"不能用作標(biāo)識符(變量或函數(shù)名、參數(shù)名等)
"use strict"; var eval = "hehe";
Uncaught SyntaxError: Unexpected eval or arguments in strict mode
11、在嚴(yán)格模式下,函數(shù)聲明無法嵌套在語句或塊中。它們只能顯示在頂級或直接顯示在函數(shù)體中
"use strict"; var arr = [1, 2, 3, 4, 5]; var index = null; for (index in arr) { function myFunc() {}; }
node控制臺:
SyntaxError: In strict mode code, functions can only be declared at top level or immediately within another function.
但是這個(gè)限制已經(jīng)在ES6中被修復(fù)
12、嚴(yán)格模式下eval用法無效
如果在 eval 函數(shù)內(nèi)聲明變量,則不能在此函數(shù)外部使用該變量。
"use strict"; eval("var testvar = 10"); console.log(testvars);
Uncaught ReferenceError: testvar is not defined
13、嚴(yán)格模式下"arguments"用法無效
字符串”arguments”不能用作標(biāo)識符(變量或函數(shù)名、參數(shù)名等)。
"use strict"; var arguments = 1;
Uncaught SyntaxError: Unexpected eval or arguments in strict mode
這個(gè)跟上面第10條的限制是差不多的。
14、函數(shù)內(nèi)的 arguments,無法更改arguments 對象的成員的值
"use strict"; function testArgs(oneArg) { arguments[0] = 20; }
在非嚴(yán)格模式下,可以通過更改 arguments[0] 的值來更改 oneArg 參數(shù)的值,從而使 oneArg 和 arguments[0] 的值都為 20。在嚴(yán)格模式下,更改 arguments[0] 的值不會(huì)影響 oneArg 的值,因?yàn)?arguments 對象只是一個(gè)本地副本。
15、不允許使用arguments.callee
"use strict"; function my(testInt) { if (testInt-- == 0) return; arguments.callee(testInt--); } my(100);
用了的下場就是這樣:
Uncaught TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them
16、不允許使用with
"use strict"; with (Math){ x = cos(3); y = tan(7); }
Uncaught SyntaxError: Strict mode code may not include a with statement
為什么要使用嚴(yán)格模式
既然這種模式這么多限制,我為什么還要用呢?閑得蛋疼嗎?當(dāng)然8是,
JavaScript作為一門一開始用于瀏覽器的腳本語言,容錯(cuò)性非常好,即使有時(shí)候你的代碼寫的不標(biāo)準(zhǔn),也不會(huì)報(bào)錯(cuò),但這有時(shí)候會(huì)變成代碼隱患。開啟了嚴(yán)格模式之后,JavaScript的一些不合理的不嚴(yán)謹(jǐn)?shù)恼Z法都會(huì)得到控制,讓你能夠更嚴(yán)謹(jǐn)?shù)臅鴮慗avaScript代碼,成為一個(gè)更好的程序員。嚴(yán)格模式是ES5時(shí)代的產(chǎn)物,ES2015已經(jīng)在普及的路上,是時(shí)候使用嚴(yán)格模式了!
參考
相關(guān)文章
JS幻燈片可循環(huán)播放可平滑旋轉(zhuǎn)帶滾動(dòng)導(dǎo)航(自寫)
本文為大家介紹下實(shí)現(xiàn)JS幻燈片可循環(huán)播放帶滾動(dòng)導(dǎo)航可平滑旋轉(zhuǎn)的全過程,效果還不錯(cuò),由需要的朋友可以參考下,希望對大家有所幫助2013-08-08uniapp使用webview嵌入vue頁面及通信實(shí)現(xiàn)方式
項(xiàng)目中有需要嵌入其他H5的頁面的業(yè)務(wù)需求,這篇文章主要給大家介紹了關(guān)于uniapp使用webview嵌入vue頁面及通信實(shí)現(xiàn)方式的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-01-01javascript下高性能字符串連接StringBuffer類
使用StringBuffer類比使用加號節(jié)省50%左右的時(shí)間,大家對于大數(shù)據(jù)的連接最好使用這個(gè)方法。2010-08-08JS實(shí)現(xiàn)根據(jù)文件字節(jié)數(shù)返回文件大小的方法
這篇文章主要介紹了JS實(shí)現(xiàn)根據(jù)文件字節(jié)數(shù)返回文件大小的方法,涉及javascript數(shù)值計(jì)算與字符串操作相關(guān)技巧,需要的朋友可以參考下2016-08-08bootstrap confirmation按鈕提示組件使用詳解
這篇文章主要為大家詳細(xì)介紹了bootstrap confirmation按鈕提示組件的使用方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08