• javascript之变量、作用域、作用域链


    一、变量    

        javascript的变量是松散类型的,所谓松散类型就是说定义的变量可以用来保存任何类型的数据。定义变量时要使用var操作符后面跟变量名。这里的var是一个关键字,如果定义变量时省略了var,那么这个变量就成了全局变量。但一般不推荐这么做,因为在局部作用域中定义全局变量会很难维护,并且会因为相应的变量不会马上就有定义而导致不必要的混乱。

    定义变量时的格式:var a="hi"; var b=false; var c=23; 还可以这么定义:var a="hi",b=false,c=23;

    二、作用域   

        作用域(scope):简单的说:就是创建一个函数是在什么环境下创建的,它控制了javascript代码运行时变量和函数可访问的范围。在javascript中,变量的作用域可分为全局作用域和局部作用域。

        1、全局作用域(globle scope):在代码中任何地方都能访问到的对象拥有全局作用域。ps:全局变量尽量少用,因为它效率低,污染全局环境,一般有以下三种方式获取全局作用域。

        (1)在代码最外层定义的函数和变量拥有全局作用域。

    var a=2;
    function b(){
       var a=4;
    }
    b();
    alert(a);//2

        (2)在函数内部没有用var定义的拥有全局作用域。(此时函数内部定义的a已经污染了全局变量定义的a了,所以在定义变量的时候尽量养成写var的习惯)

    var a=2;
    function b(){
        a=3;
        b=4;
    }
    b();
    alert(a);//3
    alert(b);//4

         (3)所有window对象的属性拥有全局作用域。(浏览器的全局对象是window,所以全局的函数和变量都是window的属性,并且拥有全局作用域)

    function a(){
        window.b=1;
    }
    a();
    alert(b);//1

       2、局部作用域(local scope):和全局作用域相反,局部作用域一般只在固定的代码段内可访问,最常见的是在函数内部,所以在一些地方也会把它称为函数作用域,如,下面的变量b就是一个局部变量,在函数的外部是访问不到它的。

    var a=function(){
        var b=1;
    }
    a();
    alert(b);//undefined

     三、作用域链
        javascript作用域是通过作用域链来实现的。javascript函数对象中拥有一个仅供javascript引擎访问的内部属性-[[scope]],[[scope]]指向一个集合,即作用域链,它决定了哪些数据能被函数访问。作用域链的用途是保证对执行环境有权访问的所有变量和函数的有序访问,

    var a=1;
    var fn1(){
       var a=9;
       function fn2(){
            alert(this.a);//1,这里的this指代的是window
            alert(a);//9
     }
      fn2();
    }
    fn1();

     上面代码的作用域链由下图表示,不要嫌丑,用PS一笔一划勾出来的啊啊!因为不会用PPT·····

         四、作用域链与javascript代码优化

      代码在运行时,变量的查找总是在作用域链的底层开始往上查找,如果第一层没有查到,就要从更高一层作用域查找,这样一直找下去,直到全局作用域,如果没有找到就返回undefined。

      从作用域链的结构可以看出,在运行期上下文的作用域中,标识符所在的位置越深,读写速度就会越慢。因为全局变量总是存在于运行期上下文作用域链的最末端,因此在标识符解析的时候,查找全局变量总是最慢的。所以在编写代码的时候,尽量少使用全局变量,尽可能的使用局部变量。

      一个好的经验法则是:如果一个跨作用域的对象被引用了一次以上,则先把它存储到局部变量里再使用,如以下代码:

    function changeColor(){
       document.getElementById("a").onclick=function(){
         document.getElementById("b").style.left="0px";
      }
    }

    这个函数引用了两次全局变量document,查找该变量必须遍历整个作用域链,直到最后在全局对象中才能找到,这段代码可以重写如下:

    function changeColor(){
       var doc=document;
       doc.getElementById("a").onclick=function(){
         doc.getElementById("b").style.left="0px";
      }
    }

    PS:这段代码比较简单,重写后不会显示出巨大的性能提升,但是如果程序中有着大量的全局变量被反复访问,那么重写后的性能代码会显著改善。

    五、作用域链的延长

    当执行流进入下列任何一个语句时,作用域链都将延长。

    1、try—catch语句的catch快;  2、with语句;

    此两个语句会在作用域的前端添加一个变量对象,对with语句来说,其变量对象中包含着指定对象的所有属性和方法所作的变量申明;对catch来说,其变量对象中包含的是被抛出的错误对象的申明,这些标量对象都是只读的。因此在with和catch中申明的变量都会被添加到所在执行坏境的变量对象中。当with和catch语句结束后,作用域链会恢复到以前的状态。值得一提的是:改变了javascript的作用域链后,代码效率会降低,访问代价会变高。

  • 相关阅读:
    JS下载文件并修改文件名
    分页查询优化
    SQL Server初体验
    LayUI样式优化
    LayUI框架应用常见问题
    SQL Server使用常见问题
    XXLJob框架入门介绍
    Java缓存框架整理
    osgearthvcpkg
    Git——commit的提交规范
  • 原文地址:https://www.cnblogs.com/ILYljhl/p/3238775.html
Copyright © 2020-2023  润新知