Overview
严格模式是采用具有限制性JavaScript变体的一种方式,从而使代码隐式地脱离“马虎模式/稀松模式/懒散模式“(sloppy)模式。
不支持严格模式与支持严格模式的浏览器在执行严格模式代码时会采用不同行为。
严格模式对正常的 JavaScript语义做了一些更改。
- 严格模式通过抛出错误来消除了一些原有静默错误。
- 严格模式修复了一些导致 JavaScript引擎难以执行优化的缺陷:有时候,相同的代码,严格模式可以比非严格模式下运行得更快。
- 严格模式禁用了在ECMAScript的未来版本中可能会定义的一些语法。
Usage
在代码中使用'use strict';
开启严格模式。
现代ES6的代码,支持 classes
和 modules
高级语言结构,它们会自动启用 use strict
。因此,如果我们使用它们,则无需添加 "use strict" 指令。
严格模式与非严格模式的区别
严格模式下变量必须声明才能使用
正常模式中,如果一个变量没有声明就赋值,默认是全局变量。严格模式禁止这种写法,在严格模式下,如果给一个没有声明的变量赋值,那代码在执行时就会抛出ReferenceError。
严格模式下禁止使用with语句
因为with语句无法在编译时就确定,属性到底归属于哪个对象,严格模式有利于编译效率提高。
with(location){
console.log(href);
}
// 严格模式:抛出语法错误
严格模式下创建eval作用域
正常模式下,js有三种变量作用域,全局作用域、局部作用域和块级作用域,正常模式下eval语句作用域取决于它所处的作用域,严格模式下eval语句本身就是作用域,不能够生成全局变量,所生成的变量只能用于eval内部。
function testEval(){
eval("var a='lxm'");
alert(a);
}
// 非严格模式:调用 alert(a)时会弹出对话框显示 lxm
// 严格模式:调用 alert(a)时会抛出 ReferenceError
可以在 eval()中声明变量和函数,但这些变量或函数只能在被求值的特殊作用域中有效,随后就将被销毁。
严格模式下禁止this关键字指向全局对象
严格模式下全局作用域中定义的函数中的this
为undefined
。
严格模式下禁止在函数内部遍历调用栈
caller
:是调用当前函数的函数的引用,即外层函数的引用
function testCaller(){
"use strict";
testCaller.caller; //报错
testCaller.arguments; //报错
}
testCaller();
严格模式下无法删除变量
只有conifgurable设置为true的对象属性才能被删除
"use strict"
var x ;
delete x; //严格模式下报语法错误
var o = Object.create(null,{'x':{
value: 1,
configurable: true
}})
delete o.x; //删除成功
严格模式下对只读属性赋值显示报错
正常模式下对一个对象的只读属性进行赋值,不会报错,只会默默失败。严格模式下将报错
"use strict";
var obj = {};
Object.defineProperty(obj,"name",{value: 'lxm',writable: false});
obj.name = 2; //报错,因为obj.name属性是不能被修改的,严格模式会报错,正常模式会失败但不报错
严格模式下,不允许对禁止扩展的对象添加新属性
"use strict";
var obj = {};
Object.preventExtensions(obj);//禁止o对象有拓展属性
obj.name = 1; //报错
严格模式下,禁止删除一个不可删除的属性
"use strict";
delete Object.prototype; //报错
严格模式下禁止重复变量声明
let a = 1;
let a = 2; // 严格模式下报错
严格模式下函数体中的arguments
非严格模式下,修改命名参数的值也会反映到 arguments 对象中,例如:
//修改命名参数的值
//非严格模式:修改会反映到 arguments 中
function showName(name){
name = "lxm";
alert(name); //"lxm"
alert(arguments[0]); //非严格模式:"lxm"
}
showName("lili");
严格模式下这两个值是完全独立的。
//修改命名参数的值
//严格模式:修改不会反映到 arguments 中
function showName(name){
"use strict"
name = "lxm";
alert(name); //"lxm"
alert(arguments[0]); //严格模式:"lili"
}
showName("lili");
严格模式下函数不能有重名的参数
重名的参数在严格模式会报错,正常模式可以通过arguments[i]
来获取对应的参数
严格模式禁止八进制数字语法
"use strict";
var sum = 015 + // !!! 语法错误
197 +
142;