JS的严格模式

ES5最早引入了严格模式的概念。通过严格模式,可以在函数内部选择进行较为严格的全局或局部的错误条件检测。可以提早知道代码中存在的错误,及时捕获一些可能呆滞编程错误的ECMAScript行为

1.使用

在需要使用严格模式的作用域顶部加上如下代码:

"use strict"

此时该作用域(或文件)中的JS代码都将处于严格模式下。

如果没有控制页面中所有脚本的权力,建议只在需要测试的特定函数中开启严格模式

2.严格模式下的限制

(1)变量

  •  不允许意外创建全局变量
    • 如在非严格模式下,可以像下面这样创建全局变量:
      •   msg = "hello"
    • 严格模式下:
      • "use strict"
        msg = "hello"    // Uncaught ReferenceError: msg is not defined
  • 另外:严格模式下对变量名也有限制。特别地,不能使用 implements、interface、let、package、private、protected、public、static 和 yield 作为变量名。这些都是保留字,将来的 ECMAScript版本中可能会用到它们。在严格模式下,用以上标识符作为变量名会导致语法错误。

(2)对象

  • 严格模式下操作对象比在非严格模式下更容易导致错误,一般来说,非严格模式下会静默失败的情况,严格模式下就会抛出错误,如:
    • 为只读属性赋值会抛出TypeError(writeable = true)
      • 非严格模式下默认失败:
        • 1     let obj = { name: "张三" }
          2     Object.defineProperty(obj, "name", {
          3         writable: false
          4     })
          5 
          6     obj.name = "李四"
          7 
          8     console.log(obj.name);  // 张三
      • 严格模式下会抛出错误:
        • 1     "use strict"
          2     let obj = { name: "张三" }
          3     Object.defineProperty(obj, "name", {
          4         writable: false
          5     })
          6 
          7     obj.name = "李四"
          8 
          9     console.log(obj.name);  // Uncaught TypeError: Cannot assign to read only property 'name' of object '#<Object>'
    • 对不可配置的属性使用delete操作符会抛出TypeError(configurable = false)
      • 非严格模式:
        • 1     let obj = { name: "张三" }
          2     Object.defineProperty(obj, "name", {
          3         configurable: false
          4     })
          5 
          6     delete obj.name
          7 
          8     console.log(obj);   // {name: "张三"}
      • 严格模式:
        • 1     "use strict"
          2     let obj = { name: "张三" }
          3     Object.defineProperty(obj, "name", {
          4         configurable: false
          5     })
          6 
          7     delete obj.name // Uncaught TypeError: Cannot delete property 'name' of #<Object>
          8 
          9     console.log(obj);
    • 对不可扩展的对象添加属性会抛出TypeError(Object.preventExtensions()、Object.seal()、Object.freeze())
      • 以上保护对象的三个方法从左到右,保护级别依次提升。具体区别见此
      • 非严格模式:
        • 1     let obj = { name: "张三" }
          2 
          3     Object.preventExtensions(obj)
          4     obj.age = 12
          5 
          6     console.log(obj);   // {name: "张三"}
      • 严格模式:
        • 1     "use strict"
          2     let obj = { name: "张三" }
          3 
          4     Object.preventExtensions(obj)
          5     obj.age = 12    // Uncaught TypeError: Cannot add property age, object is not extensible
          6 
          7     console.log(obj);  

(3)函数

  • 严格模式要求命名函数的参数必须唯一:
    • 非严格模式:没有错误,只能访问第二个参数
      • 1     function sum (num,num){
        2         console.log(num);
        3     }
        4 
        5     sum(1,2)    // 2
    • 严格模式:
      • 1     "use strict"
        2     function sum (num,num){   // Uncaught SyntaxError: Duplicate parameter name not allowed in this context
        3         console.log(num);
        4     }
        5 
        6     sum(1,2) 
  • 严格模式下,禁用了argument.callee和argument.caller
    • 非严格模式:
      • 1     function factorial(num){
        2         if(num <=1){
        3             return 1
        4         }else{
        5             return num + arguments.callee(num-1)
        6         }
        7     }
        8 
        9     console.log(factorial(100));    // 5050
    • 严格模式:
      • 1     function factorial(num){
        2         if(num <=1){
        3             return 1
        4         }else{
        5             return num + arguments.callee(num-1)
        6         }
        7     }   // Uncaught TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them
        8 
        9     console.log(factorial(100)); 
  •  还有一个限制:就是只能在脚本的顶级和在函数的内部声明函数。也就是说,在if语句中声明函数会导致语法错误

(4)eval

  • eval在包含上下文中不再创建变量或者函数
    • 非严格模式下,fn()中的eval代码执行后会在函数fn的作用域中创建一个局部变量x
      • 1     function fn(){
        2         eval("var x = 1")
        3         alert(x)
        4     }
        5     fn()  // 弹框并出现1
    • 严格模式下:
      • 1     "use strict"
        2     function fn(){
        3         eval("var x = 1")
        4         alert(x)
        5     }  // Uncaught ReferenceError: x is not defined
        6     fn()

(5)eval和arguments

  • 禁止把eval和arguments作为变量引用
  • 禁止重写eval和arguments:
    • 使用var声明
    • 赋予另外一个值
    • 尝试修改包含的值
    • 作为函数名
    • 用作命名的函数参数
    • 在try-catch语句中用作例外名

(6)this

严格模式下的函数中的this将指向undefined(在非严格模式下指向window)

原文地址:https://www.cnblogs.com/codexlx/p/14301347.html