一、函数
首先,严格模式要求命名函数参数必须唯一。看下面的例子:
// 命名参数重名
// 非严格模式:没有错误,只有第二个参数有效
// 严格模式:抛出 SyntaxError
function sum (num, num){
// 函数代码
}
在非严格模式下,这个函数声明不会抛出错误。这样可以通过名称访问第二个 num,但只能通过
arguments 访问第一个参数arguments 对象在严格模式下也有一些变化。在非严格模式下,修改命名参数也会修改 arguments
对象中的值。而在严格模式下,命名参数和 arguments 是相互独立的。例如:
// 修改命名参数的值
// 非严格模式:arguments 会反映变化
// 严格模式:arguments 不会反映变化
function showValue(value){
value = "Foo";
alert(value); // "Foo"
alert(arguments[0]); // 非严格模式:"Foo"
// 严格模式:"Hi"
}
showValue("Hi");
在这个例子中,函数 showValue()有一个命名参数 value。调用这个函数时给它传入参数"Hi",
该值会赋给value。在函数内部,value被修改为"Foo"。在非严格模式下,这样也会修改arguments[0]
的值,但在严格模式下则不会。
另一个变化是去掉了 arguments.callee 和 arguments.caller。在非严格模式下,它们分别引
用函数本身和调用函数。在严格模式下,访问这两个属性中的任何一个都会抛出 TypeError。例如:
// 访问 arguments.callee
// 非严格模式:没问题
// 严格模式:抛出 TypeError
function factorial(num){
if (num <= 1) {
return 1;
} else {
return num * arguments.callee(num-1)
}
}
let result = factorial(5);
类似地,读或写函数的 caller 或 callee 属性也会抛出 TypeError。因此对这个例子而言,访问
factorial.caller 和 factorial.callee 也会抛出错误。
另外,与变量一样,严格模式也限制了函数的命名,不允许函数名为 implements、interface、
let、package、private、protected、public、static 和 yield。
关于函数的最后一个变化是不允许函数声明,除非它们位于脚本或函数的顶级。这意味着在 if 语句中声明的函数现在是个语法错误// 在 if 语句中声明函数
// 非严格模式:函数提升至 if 语句外部
// 严格模式:抛出 SyntaxError
if (true){
function doSomething(){
// ...
}
}
所有浏览器在非严格模式下都支持这个语法,但在严格模式下则会抛出语法错误