目录
现在的浏览器是基于es3.0原有的以及es5.0新增的语法方法使用的。而es3.0和es5.0产生冲突的部分浏览器默认采用es3.0语法规范。因此es5.0产生了一个新特性——严格模式,一旦启用es5.0严格模式,es3.0和es5.0产生冲突的部分浏览器将不再兼容es3的一些不规范语法,使用全新的es5规范。
从es5.0开始,javscript有两种运行模式:正常模式和严格模式('use strict')。
严格模式的作用
1、消除javascript语法的一些不合理、不严谨之处,减少一些怪异行为;
2、消除代码运行的一些不安全性,促进代码运行的安全;
3、提高编译器效率,增加运行速度;
4、为未来新版本的javascript做好铺垫
严格模式的启用
1、"use strict" 字符串
首先启用标志为字符串是为了兼容没有es5.0的浏览器,防止报错。
其次必须放在首部。首部指其前面没有任何有效js代码和空语句(可加注释)。放在其以下都是无效的,将不会触发严格模式。
如下列代码,严格模式无法被启用。
<script>
;
"use strict";
function test(){
console.log(arguments.callee);
}
test();
</script>
2、两种模式
全局模式:
"use strict"
放在脚本文件的第一行,整个脚本都将以严格模式运行(不影响其他脚本)。
<script>
"use strict";
function test(){
console.log(arguments.callee); //报错,严格模式下限制此语法
}
test();
</script>
<script>
function demo(){
console.log(arguments.callee); //该脚本未启用严格模式,正常运行
}
demo();
</script>
局部模式:
"use strict"
放在函数体的第一行,则整个函数以严格模式运行(推荐使用)。
<script>
function test(){
"use strict";
console.log(arguments.callee);
}
test();
</script>
严格模式下的语法限制
JS是弱类型,宽松的语言。严格模式限制了很多强大的方法,降低了灵活度,但也降低了报错的概率,有利于实际开发。
1)with
- with非常强大,它可以指定with里要执行的代码体的最直接执行期上下文。缺点:改变了作用链,降低程序运行效率。因此es5.0限制使用with。
<script>
//"use strict";
var obj = {
name : "obj"
}
function test(){
var name = "scope";
with(obj){
console.log(name); // 非严格模式下打印obj
}
}
test();
</script>
<script>
"use strict";
with(document){
write("a"); // 严格模式下报错
}
</script>
2)arguments对象的限制
- 不允许对arguments赋值;
- arguments不再追踪参数的变化;
- 禁止使用arguments.callee:意味这无法在匿名函数内部调用自身了。
//ex1 :
'use strict';
function fun(a){
arguments[0] = 2;
console.log(a); // 1
console.log(arguments[0]); // 2
}
fun(1);
3) func.caller
<script>
"use strict";
function demo(){
console.log(demo.caller);
}
function test(){
demo();
}
test();
</script>
4)eval作用域
- JS中作用域有两种,全局作用域和函数作用域。严格模式带来了第三种作用域:eval作用域。
- 正常模式下,eval的作用域,取决于它处于全局作用域,还是局部作用域。
- 严格模式下,eval语句的本身就是一个作用域,不再能够产生全局变量,它内部的变量,只能在它内部使用。
<script>
'use strict'
var a = 10;
eval('var a = 20; console.log(a)'); // 20
console.log(a); //10 (正常模式下,eval修改了全局变量,因此打印20)
</script>
5)this
- 严格模式下局部的this禁止指向window,赋值什么就是什么。
<script>
"use strict";
function test(){
console.log(this);
}
test(); // 预编译过程中this为undefined
new test(); // 构造对象,此时this指向构造函数test
</script>
- func.bind /call /apply (null/undefined) 赋值啥就是啥
<script>
"use strict";
function test(){
console.log(this);
}
test.call(null); // null(非严格模式指向window)
test.apply(undefined); //undefined(非严格模式指向window)
var f = test.bind(null);
f(); // null(非严格模式指向window)
</script>
7)call/apply的第一个参数直接传入,不包装为对象
<script>
"use strict";
function test(){
console.log(this);
}
test.call("abc"); // abc (非严格模式下为String)
test.call(123); // 123 (非严格模式下为Number)
</script>
8)变量必须经过var声明才能使用
<script>
"use strict";
var a = b = 2; // b is not defined
</script>
<script>
"use strict";
for(i = 0; i < 10; i ++){
console.log(i); // i is not defined
}
</script>
上面的for循环中,i 会不小心溢出成为全局变量。但在严格模式中会报错,保证了代码后期运行的安全性。
9)重名错误
- 对象不能有重名的属性:正常模式下不报错,最后赋值的属性会覆盖前面的值,而严格模式下属于语法错误;
- 函数不能有重名的参数;
<--ex1:严格模式拒绝对象属性重名,但不报错-->
<script>
"use strict";
var obj = {
a : 1,
a : 2
}
</script>
<--ex2:严格模式下函数参数重名报错-->
<script>
"use strict";
function func(name,name){
console.log(name);
}
func(1,2);
</script>
10)对禁止扩展的对象添加新属性会报错
<script>
'use strict';
var obj = {};
Object.preventExtensions(obj); //禁止obj扩展
obj.a = 1 ; // 报错
</script>
11)对一个对象的只读属性进行赋值将报错
<script>
'use strict'
var obj = {};
Object.defineProperty(obj, 'a', {value: 1,writable:false});
obj.a = 2; // 报错
</script>
12)对删除指令的限制
- 删除系统内置的属性会报错
<script>
'use strict';
delete Object.prototype; // 报错
delete Function.prototype; // 报错
</script>
- delete使用var声明的变量或挂在window上的变量报错
<script>
'use strict';
var obj = {a:1};
window.a = 1;
delete obj; // 报错 ( 正常模式下也删除不掉经过var的变量,但不报错)
delete a; // 报错
</script>
- delete不可删除属性(isSealed或isFrozen)的对象时报错
<script>
'use strict';
var obj = {
a: 1
}
Object.seal(obj); // 密封该对象后不可删除
delete obj.a; // 报错
</script>
- 只有configurable设置为true的对象属性,才能被删除
<script>
"use strict";
var obj = Object.create(null, {'x': {
value: 1,
configurable: true
}});
delete obj.x; // true
</script>
13)函数必须声明在顶层
函数声明和函数表达式是两个不同的概念。一般函数声明都在最顶层,ES5前的JS宽松,可以写在if或for内。而在严格模式中这些写法将直接报错。
<script>
'use strict';
if (true) {
function func1(){}
}
for (var i = 0; i < 5; i++) {
function func2(){}
}
func1(); // func1 is not defined
func2(); // func2 is not defined
</script>
14)八进制表示法被禁用
<script>
'use strict'
var num = 022; // 报错
</script>
15)ES5里新增的关键字不能当做变量标示符使用
implements, interface, let, package, private, protected, public, static, yield