• JS_高程4.变量,作用域和内存问题(2)执行环境及作用域


    1.执行环境:执行环境定义了变量或函数有权访问的其他数据,决定了它们各自的行为,

          每个执行环境都有一个与之相关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中。

    2.全局执行环境

      最外围的一个执行环境。在web浏览器中,全局执行环境被认为是window对象,因此所有的全局变量和函数都是作为window对象的属性和方法创建的。(某个执行环境中的所有代码执行完毕后,该环境被销毁,保存在其中的所有变量和函数定义也随之销毁,全局执行环境直到应用程序退出,例如关闭网页或是浏览器时才会被销毁。)

    3.作用域链:当代码在一个环境中执行时,会创建变量对象的一个作用域链,作用域链的用途是:保证对执行环境有权访问的所有变量和函数的有序访问。

          

      作用域链的前端,始终都是当前执行的代码所在环境的变量对象,下一个变量对象来自包含(外部)环境,再下一个变量对象则来自下一个包含环境,这样一直延续到全局执行环境,全局执行环境的变量对象始终都是作用域链中的最后一个对象。

    4.在局部作用域中定义的变量可以在局部环境中与全局变量互换使用。

    eg:

     1 var color="red";
     2 
     3     function changeColor(){
     4         var anotherColor="blue";
     5 
     6         function swapColors(){
     7             var tempColor=anotherColor;
     8             anotherColor=color;
     9             color=tempColor;
    10 
    11             //这里可以访问到color,anotherColor,tempColor。
    12         }
    13         //这里可以访问到color,anotherColor,但是不能访问到tempColor。
    14 
    15         swapColors();
    16     }
    17     //这里只能访问color
    18 
    19     changeColor();

    注意:

      从以上代码可以看出,内部环境可以通过作用域链访问所有的外部环境,但是外部环境不能访问内部环境中的任何变量和函数。环境之间的联系是线性,有次序的。每个环境都可以向上搜索作用域,以查询变量和函数名;但是任何环境都不能向下搜索而进入另一个环境。

    5.延长作用域链

      在作用域链的前端临时增加一个变量对象,带变量对象会在代码执行后被移除。

      但执行流进入下列任一语句时,作用域链会被加长:try-catch语句的catch块,with语句。

    6.没有块级作用域

      在c语言中,由花括号封闭的代码都有自己的块级作用域,当相应的语句执行完毕后,块级作用域中定义的变量会被销毁。但是Javascript没有块级作用域,所以不会这样。

    eg:

    1  if(true){
    2         var color="red";
    3     }
    4     alert(color);//"red"

    eg:

    1  for(var i=0;i<10;i++){
    2         doSomething(i);
    3     }
    4     alert(i);//10

     注意:

      那么当我们在JavaScript中需要创建一个临时作用域时,我们可以通过创建一个新函数并且在内部定义变量。

    eg:

    1 var color="red";
    2   if(true){
    3       (function(){
    4           var color="pink";
    5           alert(color);//pink
    6       }());
    7   }
    8   alert(color);//red

    可以与下面的例子形成对比,加深理解。

    1 var color="red";
    2   if(true){
    3           var color="pink";
    4           alert(color);//pink
    5       }
    6   
    7   alert(color);//pink

    (1)声明变量:使用var声明的变量会自动被添加到最近的环境中。没有使用var声明,该变量会自动被添加到全局变量中。

    eg:

    1 function add(num1,num2){
    2         var sum=num1+num2;
    3         return sum;
    4     }
    5     var result=add(10,20);
    6     alert(result)
    7     alert(sum);

    结果:

    注意:变量sum是函数内部定义的局部变量,在函数外部是访问不到的。

    改为:

    1  function add(num1,num2){
    2         sum=num1+num2;
    3         return sum;
    4     }
    5     var result=add(10,20);
    6     alert(result)
    7     alert(sum);

    则sum也可以访问到。

    (2)查询标识符

        现在局部环境中查找,如果找不到再逐级向上查找,如果在全局变量中还是没有找到,就说明该变量尚未定义。

    eg;

    1 var color="red";
    2     function getColor(){
    3         return color;
    4     }
    5     alert(getColor());

    eg:

    1 var color="red";
    2     function getColor(){
    3         var color="blue";
    4         return color;
    5     }
    6     alert(getColor());

    注意:

    eg:

    1 var color="red";
    2     function getColor(){
    3         
    4         return color;
    5         var color="blue";
    6     }
    7     alert(getColor());//undefined

    如果是这样的顺序,由于JavaScript中变量的提升,其实该程序相当于下面的程序:

    1 var color="red";
    2     function getColor(){
    3         var color;
    4         return color;
    5         color="blue";
    6     }
    7     alert(getColor());//undefided

     变量的提升:把定义在后面的变量提升到前面中定义。注意提升的只是变量的声明,并不会把赋值也提升上去。

     函数的提升:把整个函数提到前面。

    (1)函数表达式:var foo=function foo(){.....}

    (2)函数声明: function foo(){.....}

    注意:只有函数声明的形式才能被提升。

    eg:

    1  function myTest(){
    2       foo();
    3       function foo(){        //函数提升成功
    4           alert("hello");
    5       }
    6   }
    7   myTest();
    1 function myTest(){
    2       foo();
    3       var foo=function foo(){        //函数提升失败
    4           alert("hello");
    5       }
    6   }
    7   myTest();

    把foo()调到后面就可以了:

    1 function myTest(){
    2   
    3       var foo=function foo(){        
    4           alert("hello");
    5       }
    6           foo();
    7   }
    8   myTest();
  • 相关阅读:
    bootstrap 弹出框(Popover)插件 修改title等属性选项值
    dedecms 搬家流程
    jQuery ui 百叶窗blind方向设置
    css 优先级
    dedecms 标签
    dedecms 建站相关问题
    css 透明度使用
    css 边框使用
    css 阴影使用
    js 常用判断
  • 原文地址:https://www.cnblogs.com/LinSL/p/6178943.html
Copyright © 2020-2023  润新知