JavaScript全局作用域、函数作用域和块级作用域的区别

204 阅读3分钟

作用域(Scope):函数和变量的使用范围

全局作用域:函数外部的作用域

函数作用域;函数内部的作用域

块级作用域:{ } 包裹着的代码

一、全局作用域 let uname = "奥特曼" function getName() { console.log(uname); //奥特曼 } getName() console.log(uname); //奥特曼 不管是函数里面还是函数外面都可以访问到uname变量

总结:在函数外面定义的变量,在页面的任何地方都可以访问

二、函数作用域 在es5中只有 全局作用域和函数作用域

    function getName() {
        let uname = "奥特曼"
        var age = "20"
        console.log(age);
        console.log(uname); //奥特曼
    }
    getName()
    console.log(age);  // age is not defined
    console.log(uname); //uname is not defined

注意点 全局输出时age和uanem是单独输出的,因为在执行过程中,如果前面的代码报错,就会阻塞后面的代码继续执行

当前的uname和age是在函数内部定义的,uname和age就是局部变量,只有函数内部可以访问(不包括函数嵌套,父访问子)

为什么在全局访问不到函数内部定义的变量呢? 在调用getName的时候,函数会新开辟一个作用域空间,等函数执行完以后,函数会把这个作用域关闭,并且把变量也进行销毁

三、块级作用域(block) 在es6中新增了块级作用域 :被 { } 包裹住的代码就是块级作用域( 包括函数中的{ }、if、for )

    if(true){
        let uname = '奥特曼' 
        var age="20"
        console.log(age); //20
        console.log(uname); // //奥特曼
    }
    console.log(age); //20
    console.log(uname);  //uname is not defined

同样发现 在{ }中定义的变量,用let声明的变量 在{ } 外部同样访问不到 ,但是用var 声明的可以访问到,我们到断点去看一下

我们发现用let 定义的变量 放到了Block区块中,而var声明的变量放在了Global全局当中,所以说var在块级作用域下我们可以进行访问

查了资料看到MDN说

个人理解就是var定义的变量 不管在哪定义的,都会放到window下 所以用的都是同一个作用域。

接下来看let中在{ }定义的变量

let 和 const定义的变量是有块级作用域的,只能在当前块作用域访问

总结访问变量的区别

var定义的变量,没有块的概念,可以跨块访问, 不能跨函数访问。

let定义的变量,只能在块作用域里访问,不能跨块访问,也不能跨函数访问。

const用来定义常量,使用时必须初始化(即必须赋值),只能在块作用域里访问,而且不能修改。

总结完之后再来看看为什么es6会增加块级作用域呢,知道概念不行,更要知道原理哦

  1. 内层变量覆盖外层变量

     //es5
     var uname = "奥特曼"
     function fn() {  
      console.log(uname);  //undefined
      if(false){
         var uname = "怪兽"
      }
     }
     fn()
    
     //es6
     var uname = "奥特曼"
     function fn() {  
      console.log(uname);  //奥特曼
      if(false){
         let uname = "怪兽"
      }
     }
     fn()
    

由于var声明的变量会产生变量提升会覆盖上面声明的结果,但是let会在当前产生一个块作用域

2.循环遍历泄漏为全局变量

        for (var i = 0; i < 10; i++) {
                    console.log(i);
                }
        console.log(i);  //10

        for (let j = 0; j < 10; j++) { 
            console.log(j);           
        }
        console.log(j); //j is not defined

转自csdn奥特曼