JS作用域

作者: Welkin_qing | 来源:发表于2018-06-11 21:44 被阅读25次

    一、js作用域概念---预解析规则,表达式

    域:指的是一个空间、范围、区域

    作用:通常指读和写

    所以

    作用域:指的是在一个范围内进行读或写的操作

    浏览器中对js代码进行操作的是js解析器

    js解析器的作用是:

    1.“找一些东西”(var关键字、函数、参数)

    var a=1;
    function fn1(){
    alert(2);
    }

    在上面的代码中,

    a=未定义;

    即:所有变量在正式运行之前都被赋了一个值:未定义

    fn1 = function fn1(){
    alert(2);
    }

    即:所有的函数在正式运行代码之前都是整个函数块

    注意:在js预解析中,遇到重名变量和函数时,只留函数。

    2.逐行解读代码

    通过表达式解读代码( = + * / % ++ -- ! Number() 参数)
    解析代码的过程是从仓库里找东西

    注意:表达式可以修改预解析内的值

    二、全局与局部作用域解析以及作用域链

    域的形成在js当中有两种

    1.<script></script>

    当中含有全局变量、全局函数(window)
    读取的方式是自上而下

    2.函数(作用域链)

    读取的方式是由里到外
    在js高程中有介绍道:作用域链的用途,是保证对执行环境有权访问的所有变量和函数的有序访问(其实和我总结的一样啦~~)
    下面我们来看一个代码:

    例1

    alert(a);   //function a(){alert(4);}
    var a=1;
    alert(a); //1
    function a(){alert(2);}
    alert(a);  //1
    var a=3;
    alert(a);  //3
    function a(){alert(4)}
    alert(a);  //3  //typeof(a) 为number
    a();  //报错
    

    解析:
    第一步“找” 首先解析器先找关键字找到var a=未定义,然后又找到函数a=function a(){alert(2);},则覆盖原来的a=未定义;然后又找到a =未定义;无法覆盖,继续往下,找到a=function a(){alert(4)};现在在仓库里存入a=function a(){alert(4)};

    第二步“读”从上往下看,读到alert(a),从仓库里找到刚才存入的a=function a(){alert(4)},所以输出;然后再往下第二行看见’=‘,则覆盖原来的函数,修改了原来仓库里的值使a=1;所以下一步输出a=1;再往下,函数中没有关键字,不修改仓库里的值,继续往下输出a=1;同理看见=;修改为a=3,然后输出。一直到最后a的值也是3。
    但是当调用a();这个函数时,会报错,因为在仓库里a是一个变量不是一个函数。

    再举一个例子:

    例2

    var a=1;
    function fn1(){
      alert(a);   //a=未定义
      var a=2;
    }
    fn1();
    alert(a);  //a=1
    

    解析:
    1.存入仓库里的是

    a=未定义

    fn1()=function fn1(){

    alert(a);
    var a=2;
    }

    自上而下往下读时,第一行有=;所以a=1;第二行函数不管,一直到调用fn1时,进入函数内部;

    注意1:函数内部也是类似于作用域,分为两步;找东西和逐行读代码

    进入函数内部之后,找到var a=.. ,所以函数内部仓库a=未定义;现在开始读代码,alert输出a=未定义;再往下,遇到=,给a赋值a=2;跳出函数继续往下,alert(a);

    注意2:函数内部的为局部变量,现在浏览器访问到全局的仓库里找到a=1,所以输出a=1;

    *局部作用域可以访问全局

    同理,我再将上边的代码修改一下(将函数内部的var删除):

    例3

    var a=1;
    function fn1(){
      alert(a);   //a=1
       a=2;
    }
    fn1();
    alert(a);  //a=2
    

    解析:与原来不同的是,函数内部仓库里找不到a存的值,或者换句话说,没有存入a,则需要从外部调取,所以a=1;同时函数内部修改了a的值,改为a=2;值得一提的是,此时修改的是全部变量的值,所以当函数调用完之后输出的是a=2

    例4

    var a=1;
    function fn1(a){
      alert(a);  //a=未定义
      a=2;
    }
    fn1();
    alert(a);   //a=1
    

    解析:第一步,a存入仓库:a=未定义,然后开始读代码,读取第一行使a=1;再读入函数调用,调用函数时发现函数调用使用了参数,参数a=var a...将其存入函数内部仓库,所以函数内部输出alert(a)时,a=未定义,下一步修改函数内部a=2,跳出函数;alerta(a)时,调用的是全局变量所以输出a=1;

    三、调用函数局部是数据,全局声明以及for嵌套中i的取值

    例5

    var a=1;
    function fn1(a){
      alert(a);
      a=2;  //a=1
    }
    fn1(a);
    alert(a);  //a=1
    

    解析:第一步,a存入仓库:a=未定义,然后开始读代码,读取第一行使a=1;再读入函数调用,调用函数时发现函数调用使用了参数,参数a = var a = 1;因为fn1(a)中的a来自全局,所以当读取函数内部的alert(a)时a=1;下一步修改函数内部a=2,跳出函数;alerta(a)时,调用的是全局变量所以输出a=1;

    我们需要始终记住作用域的特点:先解析再执行

    当然,如果我们想获取函数内部的值,就是获取局部变量的值
    可以通过下面两个办法:

    1.利用全局变量赋值获取

    例6

    var str ='';
    function a(){
      a='999';
      str =a ;
    }
    alert(str);
    

    2.通过函数调用

    例7

    function fn2(){
      var a ='999';
      fn3();
    }
    fn2();
    function fn3(d){
      alert(d);
    }
    

    例8

    alert( fn1 );       
    
    var a = 1;
    function fn1(){
        alert(123);
    }
    
    if( true ){
        
    }
    

    firefox不能对下面的函数进行预解析

    对于for或者if嵌套,在js高程里称作“没有块级的作用域”,上面解释道:以for语句为例,由for创建的变量i即使在for循环执行结束后,也会依旧存在于循环外部的执行环境中。

    例8

    for(var i=0;i<10;i++){
      dosomething();
    }
    alert(i)  //i=10
    

    相关文章

      网友评论

        本文标题:JS作用域

        本文链接:https://www.haomeiwen.com/subject/qsoheftx.html