JavaScript 严格模式

概述

ECMAScript 严格模式是采用具有限制性 JavaScript 变体的一种方式。其目的主要有以下几点:

  • 消除 JavaScript 语法的一些不合理、严谨的地方,减少一些怪异行为

  • 消除代码运行的一些不安全之处,保证代码运行的安全

  • 提高编译器效率,增加运行速度

  • 为未来版本的 JavaScript 做好铺垫

使用方式

对于脚本

将 use strict 放在整个脚本的第一行(必须放置在第一行,否则无效),整个脚本以严格模式运行。

1
2
3
4
<script>
"use strict"
console.log("This is in strict mode.")
</script>

上面的写法有缺点,当有多个脚本文件的时候,不利于文件的合并。变通的做法是将整个脚本文件放在立即执行的匿名函数中

1
2
3
4
(function() {
'use strict'
// follow codes
})();

将 use strict 放在函数的第一行,整个函数以严格模式运行

1
2
3
4
function strict() {
'use strict'
console.log('This is in strict mode.')
}

带来的改变

全局变量必须显示声明

1
2
3
'use strict'
v = 1 // 报错。v 未声明
for (i = 0; i < 10; i++) {} // 报错。i 未声明

禁止使用 with 语句

1
2
3
4
5
6
7
'use strict'
var v = 1
// 严格模式限制了一些动态绑定
// 在这里 with 语句无法在编译时确定属性归属于哪个对象
with (o) { // 语法错误
v = 2
}

eval 作用域

正常模式下有两种作用域( scope ):全局作用域、函数作用域。严格模式下有了第三种作用域, eval 作用域

1
2
3
4
5
'use strict'
var v = 1
// eval 创建了自身的作用域,它所生成的变量只用于 eval 内部
console.log(eval('var v = 2; v')) // 输出 2
console.log(v) // 输出 1

禁止 this 指向全局对象

1
2
3
4
5
6
7
function f() {
return !this // false, this 为全局对象,不为 null 和 undefined,所以返回 false
}
function f() {
'use strict'
return !this // true, this 不指向全局对象,为 undefined
}

禁止在函数内部遍历调用栈

1
2
3
4
5
6
function f() {
'use strict'
// properties may not be accessed on strict mode functions or the arguments objects for calls to them
f.caller // 报错
f.arguments // 报错
}

删除变量或属性的限制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
'use strict'
var a = 1
delete a // 报错,禁止删除变量
var obj = Object.create(null, {
'a': {
value: 1,
configurable: true
},
'b': {
value: 2,
configurable: false
}
})
// 只有 configurable 为 true 的对象属性才能被删除
delete obj.a // 成功
delete obj.b // 失败

显示报错

正常模式下有些行为会失败,不会报错;严格模式下将报错,情况如下:

  • 对一个对象的只读属性赋值

  • 对一个只使用 getter 方法读取的属性赋值

  • 对禁止扩展的对象添加新属性

  • 删除一个不可删除的属性

重名的错误

情况如下:

  • 对象不能有重名的属性

  • 函数不能有重名的参数

1
2
3
4
5
6
'use strict'
var obj = {
p: 1,
p: 2
}
function f(a, a, b) {}

禁止八进制表示法

1
2
3
"use strict";
// 正常模式下,整数的第一位如果是0,表示这是八进制数
var a = 0100; // 语法错误

arguments 对象的限制

arguments 对象是所有非箭头函数中都可用的局部变量

限制如下:

  • 不允许对 arguments 赋值

  • arguments 不再追踪参数变化

  • 禁止使用 arguments.callee

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
"use strict";
// 不允许对 arguments 赋值
arguments++; // 语法错误
var obj = { set p(arguments) { } }; // 语法错误
try { } catch (arguments) { } // 语法错误
function arguments() { } // 语法错误
var f = new Function("arguments", "'use strict'; return 17;"); // 语法错误

// arguments 不再追踪参数变化
function f(a) {
a = 2;
return [a, arguments[0]];
}
f(1); // 正常模式为[2,2]
function f(a) {
"use strict";
a = 2;
return [a, arguments[0]];
}
f(1); // 严格模式为[2,1]

// 禁止使用 arguments.callee
"use strict";
var f = function() {
// argumens.callee 指向当前执行的函数
return arguments.callee;
};
f(); // 报错

函数不能声明在非函数的代码块中

1
2
3
4
"use strict";
if (true) {
function f() { } // 语法错误
}

新增加的保留字

implements, interface, let, package, private, protected, public, static, yield

保留字无法作为变量名