ES5 引入严格模式
一、严格模式的使用
使用
"use strict"
表明脚本或函数开启严格模式
-
"use strict"
声明必须放在第一行,否则将导致严格模式声明无效(严格来说,是必须放在具有实际运行作用的第一行代码前,例如可以放在一个空分号后边) -
脚本中
<!-- 严格模式声明只在当前script内有效 --> <script> 'use strict'; console.log('严格模式') </script> <script> console.log('普通模式') </script>
-
函数中
function strictFunc(){ 'use strict'; console.log('严格模式') }
-
更好的方法
严格模式声明与严格模式代码均放到自执行函数内,有利于代码合并
(function (){ 'use strict'; // some code here... })()
二、严格模式的具体影响
严格模式对Javascript的语法和行为,都做了一些改变。
1. 全局变量需要显示声明
a = 10; // 普通模式将声明全局变量,严格模式将报错,声明全局变量必须使用var
2. 静态绑定
- 禁用
with
语句 - 创建
eval
作用域:eval
内部声明的变量只能在eval
中使用,不再污染外部作用域
3. this指向
-
全局function函数的this将不再指向
window
,而是undefined
function foo(){ 'use strict'; console.log(this); } foo(); // undefined
4. 函数内禁止遍历递归栈
- 禁用
funncName.caller
、funncName.arguments
function foo(){ foo.caller; foo.arguments; // 报错 }
补充:
- 函数内的
arguments
对象还是可以用的,只是函数内的funncName.arguments
不可用 (function f(){ console.log(f.arguments === arguments) })()
:false
- 函数内的
5. 显式报错
- 数据描述符的
writable
属性值为 false 时,赋值将会显式报错 - 描述符的
configurable
属性值为 false 时,delete
该属性将会显式报错 - 使用
Object.preventExtensions()
禁止对象拓展属性后,新增属性将会显式报错
6. 重命名报错
- 对象声明重复属性时将显式报错(普通模式后声明属性值会覆盖先声明属性值)
- 函数参数声明重名参数时将显式报错(普通模式函数内会默认获取后声明参数,或者使用arguments对象按序获取)
7. 禁止数字的八进制表达法
- 使用类似于
010
的八进制表达法将会报错(普通模式下010
的十进制值为8)
8. 函数内arguments对象作限制
-
禁止对
arguments
对象进行赋值(function (){ 'use strict'; arguments = []; console.log(arguments); })(1) // Uncaught SyntaxError: Unexpected eval or arguments in strict mode (function (){ 'use strict'; arguments[0] = 2; console.log(arguments[0]); })(1) // 2 注意本质是不能修改arguments这个引用(指针)的值
-
arguments
将不再跟踪参数的变化(function (num){ 'use strict'; num = 2; console.log(num, arguments[0]) })(1) // 2, 1 (function (num){ // 普通模式 num = 2; console.log(num, arguments[0]) })(1) // 2, 2
-
禁止使用
arguments.callee
这意味着我们无法在匿名函数内调用自身了
9. 函数声明必须位于顶层
(function (){
'use strict';
a();
if(true){
function a(){};
}
})() // Uncaught ReferenceError: a is not defined
补充:其实大多现代浏览器也要求函数声明必须位于顶层,否则也会报错
10. 新增一些保留字
- implements, interface, let, package, private, protected, public, static, yield
- 使用保留字作为变量名将会报错