Web全栈工程师之路(三)——JavaScript篇(十六)——作用域

以下是html代码,个人建议放在IDE里运行,边看效果,边学习~

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>JS初步(十六)——作用域</title>
    <script>
        /*  
            作用域
                - 指一个变量作用的范围
                - 在JS中一共有两种作用域:
                    1.全局作用域
                        - 直接编写在script标签中的JS代码,都在全局作用域
                        - 全局作用域在页面打开时创建,在页面关闭时销毁
                        - 在全局作用域中有一个全局对象window,它代表的是一个浏览器的窗口
                          它由浏览器创建,我们可以直接使用
                        - 在全局作用域中:
                            创建的变量都会作为window对象的属性保存
                            创建的函数都会作为window对象的方法保存
                        - 全局作用域中的变量都是全局变量,在页面的任意的部分皆可访问
                    2.函数作用域
                        - 调用函数时创建函数作用域,函数执行完毕以后,函数作用域销毁
                        - 每调用一次函数就会创建一个新的函数作用域,他们之间是互相独立的
                        - 在函数作用域中可以访问到全局作用域的变量,在全局作用域中无法访问到函数作用域的变量
                        - 当在函数作用域操作一个变量时,它会先在自身作用域中寻找,如果有就直接使用
                          如果没有,则向上一级作用域中寻找(这里的上一级不一定是全局作用域),如果没有则向上一级作用域中寻找
                          直到找到全局作用域,全局作用域可以说是最上级作用域,如果全局作用域中依然没有找到则会报错
                        - 在函数中要访问全局变量可以使用window对象
                        - 定义形参就相当于在函数作用域中声明了变量
            
            变量的声明提前
                - 使用var关键字声明的变量,会在所有的代码执行之前被声明(但是不会被赋值)
                  但是如果声明变量时不使用var关键字,则变量不会被声明提前
            
            函数的声明提前
                - 使用函数声明形式创建的函数(即function 函数名(){})会在所有的代码执行前被创建
                  所以我们可以在函数声明前面来调用函数
                - 使用函数表达式创建的函数(即var 函数名 = function(){})不会被声明提前
                  所以我们这个时候不可以在函数声明前面来调用函数

        */

        function fun(){
            var a = 123;
            console.log("这里是fun函数的输出");
        }

        // console.log(a); 输出会报错,提示a没有被定义,fun函数中的a是在fun中定义的,只会在fun中起作用

        //全局作用域
        var a = 123; //创建a时,a就成为了window对象中的一个属性

        console.log(window.a); //所以输出a也可以这样,只不过一般不用

        window.fun(); //再来试试函数

        window.console.log("这里是前面加了window的console") //同理自带的函数也可以这样用
        
        console.log(window); //输出看看,window自带的方法

        //函数作用域
        function fun2(){
            b = "这里是全局b,不过,是在fun2里修改过的全局b"; //在函数中,不适用var声明的变量都会成为全局变量
            fun3(); //输出看看(这条语句不能放在外面执行,同一个道理,出了fun2就没了)
            console.log(a); //因为fun2里已经存在a了,所以优先输出fun2中的a
            function fun3(){ //函数声明也会在函数中所有的代码执行之前执行
                console.log("这里是fun3中的代码,用的a是fun2中的:"+a); //这里fun3中没有a,但上一级的fun2中有a,所以优先输出fun2中的a
                console.log(b); //因为fun3里没有b,看向上一级fun2,fun2也没有,再看向fun2的上一级,即全局,有了,就输出
                console.log("这里是fun3中的代码,用的a是全局中的:"+window.a); //若想在函数里已有相同的变量情况下输出全局的同名变量,可以在前面加window
            }
            var a = "这里是函数fun2中的a"; //函数中变量的声明提前,不过只定义了没有值,可以将此代码提到最前面再试试看
            
        }
        /*  
            在函数作用域也有声明提前的特性,使用var关键字声明的变量,会在函数中所有的代码执行之前被声明
        */

        var a = "这里是全局a";
        var b = "这里是全局b"; //看看这里的内容是否被输出了

        fun2(); //输出看看
        // fun3(); //输出看看,提示fun3 is not defined
        
        function fun4(c){ //这里定义形参就相当于在函数作用域中声明了变量
            console.log(c); //输出看看
        }
        fun4("这里是c");
    </script>
</head>
<body>
    
</body>
</html>

相关推荐