zoukankan      html  css  js  c++  java
  • JS 全局作用域和局部作用域

    一、作用域

    1、什么是作用域(Scope)

     通常来说,一段程序代码中所用到的名字不总是有效和可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。

    JS作用域就是代码名字(变量)作用的范围

    作用域的目的:是为了提高程序的可靠性,更重要的是减少命名冲突

    2、JS的作用域的分类(ES6之前)

    JS作用域可以分为两大类:全局作用域 、局部作用域(函数作用域)

    (一)全局作用域:

      直接编写在 script 标签之中的JS代码,都是全局作用域;

      或者是一个单独的 JS 文件中的。

      全局作用域在页面打开时创建,页面关闭时销毁;

      在全局作用域中有一个全局对象 window(代表的是一个浏览器的窗口,由浏览器创建),可以直接使用。

    在全局作用域中,

    • 所有创建的变量都会作为 window 对象的属性保存。

    • 所有创建的函数都会作为 window 对象的方法保存。

     

    (二)局部作用域(函数作用域):

      在函数内部就是局部作用域,这个代码的名字只在函数的内部起作用

      调用函数时创建函数作用域,函数执行完毕之后,函数作用域销毁;

      每调用一次函数就会创建一个新的函数作用域,它们之间是相互独立的。

    实例分析:

    在这个例子里面 un函数里面的 局部作用域中 有一个 num 变量,script 标签的全局作用域中也有一个 num变量。

    (一个在全局作用域下,另一个在局部作用域下,虽然两个变量的变量名相冲突,但是并没有影响。)

    所以,在不同的作用域下,变量名相同也不受影响,这样就很有效的减少了命名冲突。

    <script>
        var num = 10;
        function nu(){
            var num = 20;
            console.log(num);
        }
        nu();
        console.log(num);
    </script>

     JS现阶段(ES6之前)没有块级作用域,被块级作用域就是用大括号({})包含的就是块级作用域。

    二、变量的作用域

    在JavaScript中,根据作用域的不同,变量可以分为两种:全局变量局部变量

    (一)全局变量

      1、在全局作用域下声明的变量叫做 全局变量在函数外部定义的变量

      2、全局变量在全局(代码的任何位置)下都可以使用;全局作用域中无法访问到局部作用域中的变量。

      3、全局变量第一种创建方式:在全局作用域下 var声明的变量是全局变量

      4、全局变量第二种创建方式:如果在函数内部,没有使用 var关键字声明直接赋值的变量也属于 全局变量。(不建议使用)

    (变量 num 直接写在 script标签下,所以 num是全局变量。)

    <script>
    var num = 10;
        function nu(){
            console.log(num);
        }
    nu(); console.log(num);
    </script>

     (二)局部变量:

      1、在局部作用域下声明的变量叫做局部变量在函数内部定义的变量

      2、局部变量只能在函数内部使用,在局部作用域中可以访问到全局变量。

      3、在函数内部 var 声明的变量就是局部变量

      4、函数的形参实际上就是局部变量

    <script>
        function nu(){
            var num1 = 10;
            num2 = 20;
            console.log(num1);
        }
        nu();
        console.log(num2);
    </script>

    (三)全局变量和局部变量的区别:

    全局变量在任何一个地方都可以使用,全局变量只有在浏览器关闭的时候才会销毁,比较占用内存资源

    局部变量只能在函数内部使用,当其所在代码块被执行时,会被初始化;当代码块执行完毕就会销毁,因此更节省节约内存空间;

     

    三、变量的声明提前和函数的声明提前

    (一) 变量的声明提前

    使用 var 关键字声明的变量,会在所有的代码执行之前被声明。(但是不会赋值)

    全局变量即使是写在最下面,也相当于在所有代码之前的最上面声明的变量。

      等价于 

     (在这个例子中最终结果返回的是 undefined,这是因为 变量a 就相当于在所有代码最上面被声明,但下面才被赋值,所以结果是 undefined未定义)

    如果声明变量的时候不使用 var 关键字,那么变量就不会被声明提前。

     

    (如果不写 var 关键字,变量声明就无法提前,所以在 console.log前面就找不到 变量,所以返回结果报错)

    (二) 函数的声明提前

    使用函数声明形式创建的函数function 函数名() {};

    它会在所有代码执行之前就被创建。所以可以在函数声明之前被调用

     等价于

    使用函数表达式创建的函数var 变量名 = function(){};

    不会被声明提前,所以不能再声明前调用。

     

    四、作用域链

    只要是代码,就有一个作用域,写在函数内部的就叫做局部作用域;

    如果函数中还有函数,那么在这个作用域中又可以诞生一个作用域;

    当在函数作用域中操作一个变量的时候,会先在自身作用域中查找,如果有就直接使用,如果没有就向上级作用域中寻找。如果全局作用域中也没有,那么就报错。

    根据内部函数可以访问可以访问外部函数变量的这种机制,用链式查找决定哪些数据能被内部函数访问,就称为函数作用域链

    作用域链:内部函数访问外部函数的变量,采取的是链式查找的方法来决定取那个结构,这种结构称之为作用域链

    作用域链的原则:就近原则

    (作用域链采用链式查找的方式,一层一层向上查找,先查找外面的嵌套的函数是否有所需内容,找到就输出相应的结果,如果没有再向上查找。就近原则

    实例一:


     下面代码最终输出的结果是多少?

     思路分析:

     按照链式查找先到上一级查找,输出内容在2级链,向上到 1级链去查找,如果 1级链也没有就继续向上查找。如果都找不到就会返回 undefined(未定义)。

    因为1级链中有 unm 值,所以输出num结果就是 123。

    实例二:


     下面代码最终输出的结果?

    注意:在更长的结构中画图分析太过于麻烦,可以从输出目标console.log(); 位置向外层的结构看,寻找最近的变量

    var a = 1;
        function fn1(){
            var a=2;
            var b='22';
            fn2();
            function fn2(){
                var a =3;
                fn3();
                function fn3(){
                    var a=4;
                    console.log('a= ' + a);  //求 a的值
                    console.log('b= ' + b);  //求 b的值
                }
            }
        }
        fn1();

    最终结果是:

  • 相关阅读:
    1063. Set Similarity
    A1047. Student List for Course
    A1039. Course List for Student
    最大公约数、素数、分数运算、超长整数计算总结
    A1024. Palindromic Number
    A1023. Have Fun with Numbers
    A1059. Prime Factors
    A1096. Consecutive Factors
    A1078. Hashing
    A1015. Reversible Primes
  • 原文地址:https://www.cnblogs.com/nyw1983/p/11992930.html
Copyright © 2011-2022 走看看