嚴格模式(Strict mode)是由ECMA-262規范定義的新興JavaScript標準,發布于2009年12月第五版。旨在改善錯誤檢查功能并且標識可能不會延續到未來JavaScript版本的腳本。ES5嚴格模式是限制性更強的JavaScript變體,它與常規JavaScript的語義不同,其分析更為嚴格。
目前,除了IE6-9,其它瀏覽器均已支持ES5嚴格模式。
一、嚴格模式的使用
嚴格模式 的使用很簡單,只有在代碼首部加入字符串 “use strict”。有兩種應用場景,一種是全局模式,一種是局部模式。
1)全局模式
'use strict'
//code
2)局部模式
將”use strict”放到函數內的第一行,如下
function() {
"use strict";
//code
}
二、嚴格模式下的執行限制
1)不使用var聲明變量嚴格模式中將不通過
我們知道JS中,不使用var聲明的變量默認轉為全局變量。但在嚴格模式中將不允許,會報語法錯誤。
'use strict'
g = 100 //錯誤
比如for循環
'use strict'
for (i=0; i<5; i++) { //錯誤
console.log(i)
}
2)任何使用’eval’的操作都會被禁止
'use strict'
var obj = {}
var eval = 3
for (var eval in obj) {}
function eval() {}
function func(eval) {}
3)eval作用域 JS中作用域有兩種,全局作用域和函數作用域。嚴格模式帶來了第三種作用域:eval作用域,如下
'use strict'
var a = 10
eval('var a = 20; console.log(a)'); //20
console.log(a) //10
4)with被禁用
'use strict'
var obj = {
name:'zhangsan',
age:100,
sex:'男'
}
with(obj) { //報錯
console.log(name);
console.log(age);
console.log(sex);
}
5)caller/callee 被禁用
function func() {
'use strict'
arguments.callee
arguments.caller
}
func()
6)對禁止擴展的對象添加新屬性會報錯
'use strict'
var obj = {}
Object.preventExtensions(obj)
obj.a = 1 // 報錯
7)刪除系統內置的屬性會報錯
'use strict'
delete Object.prototype // 報錯
delete Function.prototype // 報錯
8)delete使用var聲明的變量或掛在window上的變量報錯
'use strict'
var obj = {a:1}
window.a = 1
delete obj // 報錯
delete a // 報錯
9)delete不可刪除屬性(isSealed或isFrozen)的對象時報錯
'use strict'
var obj = {a: 1}
Object.seal(obj)
delete obj.a //報錯
10)對一個對象的只讀屬性進行賦值將報錯
'use strict'
var obj = {}
Object.defineProperty(obj, 'a', {value: 1, writable: false})
obj.a = 2 // 報錯
11)函數有重名的參數將報錯
'use strict'
function func(a, a) {
alert(a)
}
func()
而在非嚴格模式中,后面的同名參數將覆蓋前面的。
12)八進制表示法被禁用
'use strict'
var num = 022
13)arguments嚴格定義為參數,不再與形參綁定
function func(a) {
arguments[0] = 2
alert(a) // 2
}
func(1)
func調用時傳參為1,函數內部通過arguments修改為2,此時alert的為修改后的2。 而在嚴格模式中則不能被修改,如下
'use strict'
function func(a) {
arguments[0] = 2
alert(a) // 1
}
func(1)
14)函數必須聲明在頂層
我們知道函數聲明和函數表達式是兩個不同的概念。一般函數聲明都在最頂層,ES5前的JS寬松,你可以寫在if或for內。當然Firefox的解析方式與其他瀏覽器不同,見SJ9002。而在嚴格模式中這些寫法將直接報錯
'use strict'
if (true) {
function func1() { } // 語法錯誤
}
for (var i = 0; i < 5; i++) {
function func2() { } // 語法錯誤
}
15)ES5里新增的關鍵字不能當做變量標示符使用,如implements, interface, let, package, private, protected, public, static, yield
'use strict'
var let = 10 //報錯
var yield = 20
16)call/apply的第一個參數直接傳入不包裝為對象
'use strict'
function func() {
console.log(typeof this)
}
func.call('abcd') // string
func.apply(1) // number
依次為”string”,”number”。而在非嚴格模式中call/apply將對值類型的”abcd”,1包裝為對象后傳入,即兩次輸出都為”object”。
17)call/apply的第一個參數為null/undefined時,this為null/undefined 這里以call來示例
'use strict'
function func() {
console.log(this)
}
func.call(undefined) // undefined
func.call(null) // null
依次是undefined,null。而非嚴格模式中則是宿主對象,瀏覽器里是window,node.js環境則是global。
18)bind的第一個參數為null/undefined時,this為null/undefined bind是ES5給Function.prototype新增的一個方法,它和call/apply一樣在function上直接調用。它返回一個指定了上下文和參數的函數。當它的第一個參數為null/undefined時,情形和call/apply一樣,this也為null/undefined。
'use strict'
function func() {
console.log(this)
}
var f1 = func.bind(null)
var f2 = func.bind(undefined)
f1() // null
f2() // undefined
而在非嚴格模式中輸出的都是window(或global)。
“use strict” 的位置必須在首部。首部指其前面沒有任何有效js代碼。以下都是無效的,將不會觸發嚴格模式。
a)“use strict” 前有代碼, 無效
var width = 10
'use strict'
g = 100
b)“use strict” 前有個空語句,無效
;//這里是空語句
'use strict'
g = 100
function func() {
;
'use strict'
g = 200
}
function func() {
;'use strict'
localVar = 200
}
當然,“use strict”前加注釋是可以的
// strict mode
'use strict'
g = 100
function func() {
// strict mode
'use strict'
g = 200
}
func()