一.什么是严格模式
在ECMAScript5标准中,JavaScript提出了严格模式的概念:
- 严格模式是一种具有限制性的JavaScript模式,从而使代码隐式脱离了“懒散(sloppy)模式”;
- 支持严格模式的浏览器在检测到代码中有严格模式时,会以更加严格的方式对代码进行检测和执行。
严格模式对正常的JavaScript语义进行了一些限制:
- 严格模式通过抛出错误来消除一些原有的静默(silent)错误;
- 严格模式让JS引擎在执行代码时可以进行更多的优化(不需要对一些特殊的语法进行处理);
- 严格模式禁用了在ECMAScript未来版本中可能会定义的一些语法。
二.开启严格模式
1.在js文件中开启严格模式
每个文件需要单独开启。
"use strict";
var message='hello world'
console.log(message)
2.对某一个函数开启严格模式
function foo(){
"use strict";
}
foo()
三.严格模式的限制
严格模式下的严格语法限制:
- JavaScript被设计为新手开发者更容易上手,所以有时候本来错误语法,被认为也是可以正常别解析的;
- 但是这种方式可能会留下安全隐患;
- 在严格模式下,这种失误会被当做错误,以便更快发现和修正。
1.无法意外的创建全局变量
第一种:在全局作用域中
// 1.禁止意外创建全局变量
// message前没有定义使用的var,没有严格模式的时候会默认创建一个全局变量
message = "hello world"
console.log(message);
第二种:在函数作用域中
function foo() {
// 创建了一个全局的变量age,在严格模式下就是一种语法错误
age = 20
}
foo()
console.log(age);
上述这两种情况,在没有开启严格模式的时候,都不会报错。
2.严格模式会使引起静默失败(silent fail,注:不报错也没有任何效果)的赋值操作抛出异常
// 严格模式下NaN是不允许被赋值的
NaN = 123
true.name = 'ac'
var obj = { }
// 这个obj对象可以通过下面这个defineProperty函数来定义添加属性
// 不直接在大括号中添加name属性,是因为使用下面这个函数能够更加精准的配置
Object.defineProperty(obj, "name", {
configurable:false, // 是否可配置
writable: false, // 是否可写
value:"why"
})
console.log(obj.name);
// 这个name属性开启了不可写,因此它的值是不会被改变的且没有任何错误提示,但是在严格模式下会报错
obj.name = 'kobe'
// 添加了不可配置之后是不能够删除这个属性的,会报错
delete obj.name
3.严格模式下试图删除不可删除的属性
4.严格模式不允许函数参数有相同的名称
function foo(x, y, x) {
console.log(x,y,x);
}
foo(10, 20, 30)
结果是打印30,20,30,因为传入的两个相同参数,就表明是重复定义了两个x变量,结果x的值是最后这个赋值覆盖了第一个赋值。如果使用了严格模式,会报错。
5.不允许0的八进制语法
在很久之前是可以使用一种格式表示八进制var num = 0123,也就是使用0开头的数字表示八进制的数字,在严格模式下是不被允许的。
不过在es6之后可以使用另一种表示方法:
var num = 0x123 // 十六进制
var num1 = 0o123 // 八进制
var num2 = 0b100 // 二进制
6.在严格模式下,不允许使用with
7.在严格模式下,eval不再为上层引用变量
没有开启严格模式的时候,两个结果都是hello world。
8.严格模式下,this绑定不会默认转成对象
1)严格模式下,自执行函数的(默认绑定的)this绑定会由window变为undefined
未开启严格模式的时候,直接执行函数,它的this是指向window的,但是严格模式下,this绑定显示为undefined。
"use strict"
function foo() {
console.log(this);
}
foo() // undefined
2)严格模式下,其他形式的this绑定的指向不变
var obj1 = {
name: 'wh',
foo:foo
}
obj.foo() // 指向obj
但是这种情况是不会对代码编写造成影响的,因为之前编写的代码中,自执行的函数是没有使用this去引用window的,即便使用到了window中的属性,也是直接使用window去引用,例如:window.localStorage.setItem.
3)setTimeout的this
严格模式下,在setTimeout中使用箭头函数的时候,箭头函数不绑定this,因此会到上层作用域中找this的绑定。
setTimeout(() =>{
console.log(this) // window
},1000)
如果将箭头函数换成普通函数,在非严格模式下,打印出来的this是window,但是在严格模式下,与上面情况不一样的是,打印出来的结果依然是window。
setTimeout(function(){
console.log(this) // window
},1000)