ES5中的严格模式
除了正常运行模式,ECMAscript 5添加了第二种运行模式:"严格模式",这种模式使得Javascript在更严格的条件下运行
设立"严格模式"的目的,主要有以下几个:
消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为;
消除代码运行的一些不安全之处,保证代码运行的安全;
提高编译器效率,增加运行速度;
为未来新版本的Javascript做好铺垫
同样的代码,在"严格模式"中可能会有不一样的运行结果,一些在"正常模式"下可以运行的语句,在"严格模式"下将不能运行
这体现了Javascript更合理、更安全、更严谨的发展方向,主流浏览器都已经支持它,许多大项目已经开始全面拥抱它
进入严格模式标志:"use strict"; 语句
该语句必须放到第一行,严格来讲该语句之前不能有产生实际运行结果的语句,如跟在一个空的分号后面时可以不是第一行
如果不在"第一行"则无效,仍然以"正常模式"运行
一、放在脚本文件的第一行:整个脚本都将以"严格模式"运行
二、在<script>标签中编写的js代码中:每个标签中的脚本运行模式相互独立
<script>
"use strict";
console.log("这是严格模式。");
</script>
some_html
<script>
console.log("这是正常模式。");
</script>
上例中,一个网页中依次有两段脚本,前一个script标签是严格模式,后一个不是
三、针对单个函数:放在函数体的第一行,则整个函数以"严格模式"运行
严格模式的语法和行为
一、变量必须声明后再使用
二、静态绑定
Javascript语言的一个特点,就是允许"动态绑定",即某些属性和方法到底属于哪一个对象,不是在编译时确定的,而是在运行时确定的
严格模式对动态绑定做了一些限制。某些情况下,只允许静态绑定。也就是说,属性和方法到底归属哪个对象,在编译阶段就确定。这样做有利于编译效率的提高,也使得代码更容易阅读,更少出现意外
具体来讲涉及with语句和eval语句
2.1 禁止使用with语句,with语句无法在编译时确定属性到底归属哪个对象
2.2 创设eval作用域
正常模式下,eval语句的作用域,取决于它处于全局作用域,还是处于函数作用域
严格模式下eval语句本身就是一个作用域,不再能够生成全局变量了
三、增强的安全措施
3.1 禁止this关键字指向全局对象,严格模式下,this的值为undefined
3.2 禁止在函数内部使用fn.caller和fn.arguments获取函数调用的堆栈
四、变量默认禁止删除,只有configurable设置为true的对象属性,才能被删除,默认为false
但是可以删除属性
delete name; //严格模式报错
delete global['name'] // 严格模式删除全局变量成功
五、显式报错,之前一些操作不合规或失败不会有提示,现在改为显式报错
5.1 对一个对象的只读属性进行赋值
5.2 对一个使用getter方法读取的属性进行赋值
5.3 对禁止扩展的对象添加新属性
5.4 删除一个不可删除的属性
六,新增重名语法错误
6.1 对象不能有重名的属性,正常模式下,对象的重名属性后面的会覆盖前面的
6.2 函数不能有重名的参数,正常模式下,如果函数有多个重名的参数,可以用arguments[i]读取
七、禁止八进制表示法
正常模式下,整数的第一位如果是0,表示这是八进制数,如0100等于十进制的64
严格模式禁止这种表示法,整数第一位为0,将报错
八、arguments对象的限制
arguments是函数的参数对象,严格模式对它的使用做了限制
8.1 不允许对arguments赋值
8.2 arguments不再追踪参数的变化
function f(a) {
//"use strict";
a = 2;
console.log(a, arguments[0]);
}
f(1);
// 正常模式为 2 2
// 严格模式为 2 1
8.3 禁止使用arguments.callee,也就是说无法在匿名函数内部调用自身了
九、函数声明必须在顶层
只允许在全局或函数作用域声明函数
不允许在其他代码块内声明函数,如if语句中,for语句中都是不允许的
这是为将来Javascript的新版本会引入"块级作用域"做准备
十、增加保留关键字
新增了一些保留字
implements, interface, let, package, private, protected, public, static, yield
使用这些词作为变量名将会报错
ECMAscript第五版本身还增加了另一些保留字:class, enum, export, extends, import, super