嚴(yán)格模式(Strict mode)是由ECMA-262規(guī)范定義的新興JavaScript標(biāo)準(zhǔn),第五版發(fā)布于2009年12月。旨在改善錯(cuò)誤檢查功能并且標(biāo)識(shí)可能不會(huì)延續(xù)到未來(lái)JavaScript版本的腳本。ES5嚴(yán)格模式是限制性更強(qiáng)的JavaScript變體,它與常規(guī)JavaScript的語(yǔ)義不同,其分析更為嚴(yán)格。
目前,除了IE6-9,其它瀏覽器均已支持ES5嚴(yán)格模式。
嚴(yán)格模式的使用很簡(jiǎn)單,只有在代碼首部加入字符串 "use strict"。有兩種應(yīng)用場(chǎng)景,一種是全局模式,一種是局部模式。
1 2 3 | 'use strict' var globalVal = 100 console.log(globalVal) |
執(zhí)行后輸出了100,與非嚴(yán)格模式?jīng)]什么區(qū)別。
將"use strict"放到函數(shù)內(nèi)的第一行,如下
1 2 3 4 5 6 | function func() { 'use strict' var localVal = 200 console.log(localVal) } func() |
執(zhí)行后輸出了200,與非嚴(yán)格模式也沒(méi)用什么區(qū)別。
如果你想定義一個(gè)模塊或者一個(gè)小庫(kù),自然采用一個(gè)匿名函數(shù)自執(zhí)行是不錯(cuò)的選擇
1 2 3 4 5 | ~ function () { "use strict" ; // Define your library strictly... }(); |
“use strict” 的位置是很講究的,必須在首部。首部指其前面沒(méi)有任何有效js代碼。以下都是無(wú)效的,將不會(huì)觸發(fā)嚴(yán)格模式。
a)“use strict” 前有代碼
1 2 3 | var width = 10 'use strict' globalVar = 100 |
b)“use strict” 前有個(gè)空語(yǔ)句都不行
1 2 3 | ; 'use strict' globalVar = 100 |
或
1 2 3 4 5 | function func() { ; 'use strict' localVar = 200 } |
或
1 2 3 4 | function func() { ; 'use strict' localVar = 200 } |
當(dāng)然,“use strict”前加注釋是可以的
1 2 3 | // strict mode 'use strict' globalVar = 100 |
或
1 2 3 4 5 6 | function func() { // strict mode 'use strict' localVar = 200 } func() |
上面舉的兩個(gè)例子,在嚴(yán)格模式中輸出與普通模式?jīng)]用什么區(qū)別。下面就不一樣了。
我們知道JS是弱類型,寬松的語(yǔ)言。不使用var聲明的變量默認(rèn)轉(zhuǎn)為全局變量。但在嚴(yán)格模式中將不允許,會(huì)報(bào)語(yǔ)法錯(cuò)誤。
1 2 | 'use strict' globalVal = 100 |
執(zhí)行,F(xiàn)irebug提示如下
又如全局的for循環(huán)
1 2 3 4 | 'use strict' for (i=0; i<5; i++) { console.log(i) } |
這種寫法在非嚴(yán)格模式中很危險(xiǎn),i 會(huì)不小心溢出成為全局變量。但在嚴(yán)格模式中會(huì)報(bào)錯(cuò)
局部模式
1 2 3 4 5 6 | function func() { 'use strict' localVal = 200 console.log(localVal) } func() |
執(zhí)行,F(xiàn)irebug報(bào)錯(cuò)
因此,嚴(yán)格模式中聲明變量務(wù)必記得加一個(gè)var。
1 2 3 4 5 6 7 8 9 | 'use strict' var obj = {} var eval = 3 obj.eval = 1 obj.a = eval for ( var eval in obj) {} function eval() {} function func(eval) {} var func = new Function( 'eval' ) |
Firebug報(bào)錯(cuò)
JS中作用域有兩種,全局作用域和函數(shù)作用域。嚴(yán)格模式帶來(lái)了第三種作用域:eval作用域,如下
1 2 3 4 | 'use strict' var a = 10 eval( 'var a = 20; console.log(a)' ) console.log(a) |
Firebug控制臺(tái)依次輸出了20,10。eval是在全局模式下(非函數(shù)內(nèi))的,如果不加嚴(yán)格模式,此時(shí)修改的是全局的a。即輸出20,20。見(jiàn) eval與window.eval的差別。
1 2 3 4 | 'use strict' with ({a:1}) { } |
Firebug報(bào)錯(cuò)
1 2 3 4 5 6 | function func() { 'use strict' arguments.callee arguments.caller } func() |
Firebug報(bào)錯(cuò)
1 2 3 4 | 'use strict' var obj = {} Object.preventExtensions(obj) obj.a = 1 // 報(bào)錯(cuò) |
Firebug報(bào)錯(cuò)
1 2 3 | 'use strict' delete Object.prototype // 報(bào)錯(cuò) delete Function.prototype // 報(bào)錯(cuò) |
Firebug 報(bào)錯(cuò)
1 2 3 4 5 | 'use strict' var obj = {a:1} window.a = 1 delete obj // 報(bào)錯(cuò) delete a // 報(bào)錯(cuò) |
Firebug報(bào)錯(cuò)
1 2 3 4 | 'use strict' var obj = {a: 1} Object.seal(obj) delete obj.a |
Firebug報(bào)錯(cuò)
1 2 3 4 | 'use strict' var obj = {} Object.defineProperty(obj, 'a' , {value: 1, writable: false }) obj.a = 2 // 報(bào)錯(cuò) |
Firebug報(bào)錯(cuò)
1 2 3 4 5 | 'use strict' var obj = { a: 1, a: 2 } |
Firebug報(bào)錯(cuò)
而在非嚴(yán)格模式中,后面的屬性將覆蓋前面的屬性,即obj.a等于2。
1 2 3 4 5 | 'use strict' function func(a, a) { alert(a) } func() |
Firebug報(bào)錯(cuò)
而在非嚴(yán)格模式中,后面的同名參數(shù)將覆蓋前面的。
1 2 | 'use strict' var num = 022 |
Firebug報(bào)錯(cuò)
先看非嚴(yán)格模式代碼
1 2 3 4 5 | function func(a) { arguments[0] = 2 alert(a) // 2 } func(1) |
func調(diào)用時(shí)傳參為1,函數(shù)內(nèi)部通過(guò)arguments修改為2,此時(shí)alert的為修改后的2。 而在嚴(yán)格模式中則不能被修改,如下
1 2 3 4 5 6 | 'use strict' function func(a) { arguments[0] = 2 alert(a) // 1 } func(1) |
顯示的嚴(yán)格的為傳入的1。
其實(shí)有點(diǎn)還有點(diǎn)復(fù)雜,如果alert的是arguments[0],實(shí)際在嚴(yán)格模式中仍然被修改為2了。如下
1 2 3 4 5 6 | 'use strict' function func(a) { arguments[0] = 2 alert(arguments[0]) // 2 } func(1) |
可以參考下 僅Chrome中函數(shù)實(shí)參與形參發(fā)生關(guān)聯(lián)
我們知道函數(shù)聲明和函數(shù)表達(dá)式是兩個(gè)不同的概念。一般函數(shù)聲明都在最頂層,ES5前的JS寬松,你可以寫在if或for內(nèi)(強(qiáng)烈鄙視這種寫法)。當(dāng)然Firefox的解析方式與其他瀏覽器不同,見(jiàn)SJ9002。而在嚴(yán)格模式中這些寫法將直接報(bào)錯(cuò)
1 2 3 4 5 6 7 | 'use strict' if ( true ) { function func1() { } // 語(yǔ)法錯(cuò)誤 } for ( var i = 0; i < 5; i++) { function func2() { } // 語(yǔ)法錯(cuò)誤 } |
Firebug報(bào)錯(cuò)
1 2 3 | 'use strict' var let = 10 var yield = 20 |
Firebug報(bào)錯(cuò)
1 2 3 4 5 6 | 'use strict' function func() { console.log( typeof this ) } func.call( 'abcd' ) // string func.apply(1) // number |
Firebug輸出如下
依次為"string","number"。而在非嚴(yán)格模式中call/apply將對(duì)值類型的"abcd",1包裝為對(duì)象后傳入,即兩次輸出都為"object"。
這里以call來(lái)示例
1 2 3 4 5 6 | 'use strict' function func() { console.log( this ) } func.call(undefined) // undefined func.call( null ) // null |
Firebug輸出如下
依次是undefined,null。而非嚴(yán)格模式中則是宿主對(duì)象,瀏覽器里是window,node.js環(huán)境則是global。
bind是ES5給Function.prototype新增的一個(gè)方法,它和call/apply一樣在function上直接調(diào)用。它返回一個(gè)指定了上下文和參數(shù)的函數(shù)。當(dāng)它的第一個(gè)參數(shù)為null/undefined時(shí),情形和call/apply一樣,this也為null/undefined。
1 2 3 4 5 6 7 8 | 'use strict' function func() { console.log( this ) } var f1 = func.bind( null ) var f2 = func.bind(undefined) f1() // null f2() // undefined |
而在非嚴(yán)格模式中輸出的都是window(或global)。
相關(guān):
http://msdn.microsoft.com/library/br230269.aspx
http://java-script.limewebs.com/strictMode/test_hosted.html
http://dmitrysoshnikov.com/ecmascript/es5-chapter-2-strict-mode/
http://javascriptweblog.wordpress.com/2011/05/03/javascript-strict-mode/
JavaScript中delete操作符不能刪除的對(duì)象
聯(lián)系客服