概述

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

RoOK1E
0 声望4 粉丝