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

2021年6月20日 14点热度 0条评论 来源: 奥特曼 

作用域(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

 

    原文作者:奥特曼 
    原文地址: https://blog.csdn.net/m0_46846526/article/details/118071919
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系管理员进行删除。