严格模式(strict mode)是JavaScript定义的一种不同的解析与执行模型。ECMAScript 5引入了严格模式,在此模式下,关于ECMAScript 3中的一些不确定的行为将得到处理,对一些不安全的操作也会抛出错误。
"use strict"; //启用严格模式
看似字符串,其实是一个编译指示,告诉支持的JavaScript引擎切换到严格模式。
可以说严格模式为JavaScript这门语言容易出错的地方施加了限制。我们可以从以下例子观察到严格模式与常规模式下的一些区别。
arguments
首先:ECMAScript 中函数的参数在内部是用一个数组表示的,在函数体内可以通过arguments对象访问这个参数数组,从而获取到传递给函数的每一个参数。
在非严格模式下,定义一个函数:
function doAdd(num1, num2) {
arguments[1] = 10; //重写了第二个参数的值即num2
console.log(num1 , num2);
}
doAdd(1, 2); //输出: 1 10
在非严格模式下,每次执行doAdd()函数,都会重写第二个参数(即arguments[1]),将第二个参数的值重写为10,因为arguments对象中的值会自动反映到对应的命名函数,所以修改arguments[1],也就是修改了num2,结果是它们的值都会同步。
而严格模式下对使用arguments对象使用了限制,像上述例子中给arguments[1]重写会发生语法错误(该代码将不会执行)。如:
function doAdd(num1, num2) {
"use strict"; //严格模式
arguments[1] = 10; //严格模式下重写无效,该代码不执行
console.log(num1 , num2);
}
doAdd(1, 2); //输出: 1 2
在严格模式下利用arguments给参数赋值也显得无意义了。
递归
递归函数应该很熟悉了,就是一个函数通过名字调用自己的过程。
下面是一个经典的递归阶乘函数:
function fac(num) {
if(num <= 1) {
return 1;
} else {
return num * fac(num - 1);
}
}
但是通过函数名调用自己的方式容易导致一些不容易预测的错误,比如当我们给fac变量赋值null,则后面访问fac时会出错。我们通常会使用arguments.callee解决这个问题:
function fac(num) {
if(num <= 1) {
return 1;
} else {
return num * arguments.callee(num - 1);
}
}
arguments.callee是一个指向正在执行的函数的指针。
这个结局看似很美满,但是严格模式下是不允许脚本访问arguments.callee,访问这个属性会导致错误。但是可以通过命名函数表达式来解决:
var fac = (function f(num) {
if(num <= 1) {
return 1;
} else {
return num * f(num - 1);
}
});
这样子,f()在运行时始终保持,不会受到外界的干扰。
严格模式为我们提供了更多的规范和限制,关于严格模式还有很多注意事项,之后会慢慢补充。