嚴格模式

qq_46670991發表於2020-10-29

概述

嚴格模式是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

相關文章