概述
嚴格模式是ES5進入標準的
目的是為了:
- 明確禁止一些不合理 不嚴謹的語法 減少JS語言的一些怪異行為
- 增加更多報錯的場合 保證程式碼執行的安全
- 提高編譯效率 增加執行速度
- 為新版的JS語法做鋪墊
如何開啟
使用一段字串 "use strict"
全域性開啟嚴格模式
use strict放在JS檔案的第一行,整個JS都將以嚴格模式執行
'use strict'
console.log('這是嚴格模式')
----------
console.log('這是正常模式')
嚴格模式必須從程式碼一開始就生效
'use strict'
v=200;
console.log(v) //ReferenceError: v is not defined
----------
v=200;
console.log(v) //200
'use strict'
函式開啟嚴格模式
use strict放在函式體的第一行,則整個函式以嚴格模式執行
function strict(){
'use strict' //開啟嚴格模式
return '這是嚴格模式'
}
strict() //這是嚴格模式
如果一塊程式碼是嚴格模式,另一塊程式碼不是,它們的合併就可能出錯。嚴格模式的程式碼在前,則合併後的程式碼都是嚴格模式;如果正常模式的程式碼在前,則合併後的程式碼都是正常模式。這兩種情況下,合併後的結果都是不正確的。這時可以把整個程式碼放在一個立即執行的匿名函式之中。
(function(){
'use strict';
//其他程式碼
})()
顯式報錯
嚴格模式使得JS的語法變得更嚴格,更多的操作會顯式報錯。其中有些操作,在正常模式下只會靜默失敗,不會報錯
只讀屬性不可寫
嚴格模式下,對只讀屬性賦值會報錯
'use strict'
var obj=Object.definedProperty({},'name',{
value:'Rookie',
writable:false
})
obj.name='Faker'; //TypeError: Cannot assign to read only property 'name' of object '#<Object>'
刪除不可配置屬性也會報錯
'use strict'
var obj=Object.definedProperty({},'sex',{
value:'male',
configurable:false
})
delete obj.sex //TypeError: Cannot delete property 'sex' of #<Object>
只設定了取值器的屬性不可寫
嚴格模式下,對一個只有取值器(getter)、沒有存值器(setter)的屬性賦值,會報錯
'use strict'
var obj={
get v(){return 1}
}
obj.v=2; //TypeError: Cannot set property v of #<Object> which has only a getter
禁止擴充套件的物件不可擴充套件
嚴格模式下,對禁止擴充套件的物件新增新屬性會報錯。
'use strict'
var obj={}
Object.preventExtensions(obj);
obj.name = 'object' //TypeError: Cannot add property name, object is not extensible
eval、arguments 不可用作標識名
嚴格模式下,使用eval或者arguments作為標識名,將會報錯
'use strict'
var eval = 3;
var arguments =4;
function fn(eval){}
var fun =function eval(){}
var xxx=new Function('arguments',"use strict",return 17)
// SyntaxError: Unexpected eval or arguments in strict mode
函式不能有重名的引數
正常模式下,如果函式有多個重名的引數,可以用arguments[i]讀取。嚴格模式下屬於語法錯誤
function(a,a,b){
'use strict'
return a+b
} // SyntaxError: Duplicate parameter name not allowed in this context
arguments的不同
嚴格模式下 arguments物件的行為有所不同
- 非嚴格模式下 修改命名引數的值會反應到arguments物件中
- 嚴格模式下 命名引數與arguments物件是完全獨立的
function fn(x){
x='Hello';
console.log(x); //Hello
console.log(arguments[0]) //Hello
};
fn('HOLA')
----------
function fn(x){
'use strict'
x='Hello';
console.log(x); //Hello
console.log(arguments[0]) //HOLA
};
fn('HOLA')
其他問題
禁止使用 arguments.callee
正常模式下呼叫沒有什麼作用,但是不會報錯
var f =function(){
return arguments.callee
}
f()
嚴格模式明確規定,函式內部使用arguments.callee將會報錯
var f=function(){
'use strict'
return arguments.callee
}
f() //TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them
禁止刪除變數
嚴格模式下無法刪除變數,如果使用delete命令刪除一個變數,會報錯
'use strict'
var color ='red';
delete color //SyntaxError: Delete of an unqualified identifier in strict mode.
增加
正常模式下,JavaScript 語言有兩種變數作用域(scope):全域性作用域和函式作用域。嚴格模式創設了第三種作用域:eval作用域。
正常模式下,eval語句的作用域,取決於它處於全域性作用域,還是函式作用域。嚴格模式下,eval語句本身就是一個作用域,不再能夠在其所執行的作用域創設新的變數了,也就是說,eval所生成的變數只能用於eval內部 eval 作用域
(function () {
'use strict';
var x = 2;
console.log(eval('var x = 5; x')) // 5 eval語句內部是一個獨立作用域,所以內部的變數x不會洩露到外部
console.log(x) // 2
})()
禁止this指向全域性物件
正常模式下,函式內部的this可能會指向全域性物件,嚴格模式禁止這種用法,避免無意間創造全域性變數
function f() {
'use strict'
console.log(this === undefined);
}
f() //true 嚴格模式的函式體內部this是undefined
使用建構函式時 如果沒有使用new關鍵字,這時this不再指向全域性物件,而是報錯
function f(){
'use strict';
this.a=1
}
f() //ReferenceError: f is not defined
嚴格模式下,函式直接呼叫時(不使用new呼叫),函式內部的this表示undefined(未定義),因此可以用call、apply和bind方法,將任意值繫結在this上面。正常模式下,this指向全域性物件,如果繫結的值是非物件,將被自動轉為物件再繫結上去,而null和undefined這兩個無法轉成物件的值,將被忽略
嚴格模式
'use strict';
function fun() {
return this;
}
console.log(fun()); //undefined
console.log(fun.call(2)); //2
console.log(fun.call(true)); // true
console.log(fun.call(null)); //null
console.log(fun.call(undefined)); //undefined