【JavaScript】05. 作用域

139 阅读3分钟

这是我参与8月更文挑战的第5天,活动详情查看:8月更文挑战

作用域

01. 作用域

(1)概念

  • 作用域就是一套规则,用于确定在何处以及如何**查找变量(标识符)**的规则
  • 或者说是在代码运行时,变量的可访问性

(2)两个作用域

  • 全局作用域
    • 程序的最外层作用域,始终存在
    • 定义在全局作用域下的变量就是全局变量
      • 全局变量在任何地方都可以使用
  • 函数作用域
    • 在函数定义时才会被创建
    • 定义在局部作用域下(函数内部)的变量就是局部变量
      • 局部变量只在局部作用域下生效,且会覆盖同名的全局变量

(3)作用域链

  • 当查找(访问)变量时,采取的是一种链式查找的方式,即,从内到外、从下到上的方式,去查找作用域下的变量

    • 当前作用域开始查找
    • 如果没有,则由底向上,到最近的一层父级作用域下查找
    • 如果没有,则重复上述步骤,直到查找到,或者到全局作用域,则停止
  • 我们把这种嵌套的作用域的结构称为**作用域链**

(4)词法作用域

  • 词法作用域:在函数被定义的时候,它的作用域就已经确定

    • 和在哪里执行没有关系,因此词法作用域也被称为 静态作用域
    var value = 1;
    
    function foo() {
      console.log(value);
    }
    
    function bar() {
      var value = 2;
      foo();
    }
    
    bar(); // 1
    
    // 这里 foo() 是在全局作用域下定义的,所以它的外层作用域是 全局作用域
    // 与 foo() 在哪里执行时没有关系的,
    // 所以 bar() 的输出结果为:1
    
    

(5)块级作用域

  • 简单来说,一对花括号{}之间的区域就是块级作用域区域

  • 且,需要使用letconst关键字来创建块级作用域

    • var声明的变量没有块级作用域
  • 特别的:

    在现有浏览器机制中

    如果在块级作用域中,遇到function定义的变量——命名函数(是匿名函数就没事)

    那么,它定义处的代码之后出现的变量,只对当前块起作用,对外层上下文没有影响

    尽量避免在块级作用域中声明函数

    console.log(a) // undefined -- 因为变量提示
    var a = 0
    console.log(a) // 0
    if (true) {
        console.log(a) // f a(){} -- 因为函数提升到当前块级作用域顶部
        
        a = 1 // 这里的 a ,改变的是全局的 a
        
        console.log(a) // 1
        
        // 当块级作用域中遇到命名函数,那么其【定义处】之后的代码
        // 	出现的变量,都将是新的变量,只对当前块级作用域生效,对上一层没有任何影响
        function a() {} 
        
        a = 11 // 这里的 a ,改变的是块级作用域内部的函数 a
        
        console.log(a) // 11
    }
    console.log(a) // 1
    
    // 以上代码可这样理解
    var a1 = 0
    if(true) {
        function a2(){}
        a1 = 1
        a2 = 11
    }
    

全局变量声明后,可以重复使用,但也意味着,在某一处进行了更改,则会影响全局——全局污染

而局部变量时不存在这个问题的,但局部变量又无法重复使用

因此,如果希望有一种变量即可以重复使用,有不会污染全局,就可以使用——闭包(下一篇文章)


本人前端小菜鸡,如有不对请谅解