严格模式:使用严格模式的好处是可以提早知道代码中存在的错误,及时捕获一些可能导致编程错误的 ECMAScript 行为。

严格模式的选择使用

严格模式的编译指示(pragma): “use strict”;,支持严格模式的引擎会启动这种模式,而不支持该模式的引擎就当遇到了一个未赋值的字符串字面量,会忽略这个编译指示。

  • 在全局作用域中(函数外部)给出这个编译指示,则整个脚本都将使用严格模式。
  • 在函数作用域中给出这个编译指示,则这个函数将使用严格模式
    1. function test () {
    2. "use strict";
    3. ...
    4. }

    严格模式的规范

    变量

  1. 不允许意外创建全局变量,给一个没有声明的变量赋值,那代码在执行时就会抛出 ReferenceError

    1. // 未声明变量
    2. // 非严格模式:创建全局变量
    3. // 严格模式:抛出 ReferenceError
    4. message = "Hello world! ";
  2. 不能对变量调用 delete 操作符

    1. //删除变量
    2. //非严格模式:静默失败
    3. //严格模式:抛出 ReferenceError
    4. var color = "red";
    5. delete color;
  3. 严格模式下对变量名也有限制,不能使用 implements、interface、let、package、 private、protected、public、static 和 yield 标识符作为变量名,使用以上标识符作为变量名会导致语法错误。

    对象

  4. 为只读属性赋值会抛出 TypeError

  5. 对不可配置的(nonconfigurable)的属性使用 delete 操作符会抛出 TypeError
  6. 为不可扩展的(nonextensible)的对象添加属性会抛出 TypeError
  7. 使用对象字面量时,属性名必须唯一

    1. // 重名属性
    2. // 非严格模式:没有错误,以第二个属性为准
    3. // 严格模式:抛出语法错误
    4. var person = {
    5. name: "Nicholas",
    6. name: "Greg"
    7. };

    函数

  8. 严格模式要求命名函数的参数必须唯一

    1. //重名参数
    2. //非严格模式:没有错误,只能访问第二个参数
    3. //严格模式:抛出语法错误
    4. function sum (num, num){
    5. // todo
    6. }
  9. 在非严格模式下,修改命名参数的值也会反映到arguments对象中,而严格模式下这两个值是完全独立的

    1. //修改命名参数的值
    2. //非严格模式:修改会反映到 arguments 中
    3. //严格模式:修改不会反映到 arguments 中
    4. function showValue(value) {
    5. value = "Foo";
    6. console.log(value); //"Foo"
    7. console.log(arguments[0]); //非严格模式:"Foo",严格模式:"Hi"
    8. }
    9. showValue("Hi");
  10. arguments.callee 和 arguments.caller,在非严格模式下,这两个属性一个引用函数本身,一个引用调用函数。而在严格模式下,访问哪个属性都会抛出 TypeError

    1. //访问 arguments.callee
    2. //非严格模式:没有问题
    3. //严格模式:抛出 TypeError
    4. function factorial(num){
    5. if (num <= 1) {
    6. return 1;
    7. } else {
    8. return num * arguments.callee(num-1)
    9. }
    10. }
    11. var result=factorial(5);
  11. 严格模式对函数名也做出了限制,不允许用implements、interface、let、package、private、protected、public、static 和 yield 作为函数名

  12. 只能在脚本的顶级和在函数内部声明函数

    1. //在 if 语句中声明函数
    2. //非严格模式:将函数提升到 if 语句外部
    3. //严格模式:抛出语法错误
    4. if (true){
    5. function doSomething(){
    6. // todo
    7. }
    8. }

    eval( )

  13. 在严格模式中,它在包含上下文中不再创建变量或函数

    1. //使用 eval()创建变量
    2. //非严格模式:弹出对话框显示 10
    3. //严格模式:调用 alert(x)时会抛出 ReferenceError
    4. function doSomething(){
    5. eval("var x=10");
    6. alert(x);
    7. }
  14. 可以在 eval()中声明变量和函数,但这些变量或函数只能在被求值的特殊作用域中有效,随后就将被销毁

    1. "use strict";
    2. var result = eval("var x=10, y=11; x+y");
    3. alert(result); // 21

    eval 和 arguments

    严格模式已经明确禁止使用 eval 和 arguments 作为标识符,也不允许读写它们的值。

    1. // 把 eval 和 arguments 作为变量引用
    2. // 非严格模式: 没问题,不出错
    3. // 严格模式: 抛出语法错误
    4. var eval = 10;
    5. var arguments = "Hello world!";

    抑制this

    在非严格模式下使用函数的 apply()或 call()方法时,null 或 undefined 值会被转换为全局 对象。而在严格模式下,函数的 this 值始终是指定的值,无论指定的是什么值。

    // 访问属性
    // 非严格模式: 传入null, 函数的this值是全局对象
    // 严格模式: 抛出错误,因为this的值为 null
    var color = "red";
    function displayColor(){
     alert(this.color);
    }
    displayColor.call(null);
    

    其他变化

  15. 非严格模式下的 with 语句能够改变解析标识符的路径。严格模式下,with 被简化掉了

    //with 的语句用法
    //非严格模式:允许
    //严格模式:抛出语法错误
    with(location){
     alert(href);
    }
    
  16. 严格模式去掉了 JavaScript 中的八进制字面量

    //使用八进制字面量 
    //非严格模式:值为 8 
    //严格模式:抛出语法错误
    var value = 010;
    
  17. 严格模式下 parseInt()的行为,八进制字面量在严格模式下会被当作以 0 开头的十进制字面量

    //使用 parseInt()解析八进制字面量 
    //非严格模式:值为 8 
    //严格模式:值为 10
    var value = parseInt("010");
    

原文链接
原文链接