• js---07 js预解析,作用域---闭包


    js解析器首先不会逐行读代码,这是第二部了。
    首先 根据var找到变量,根据function找函数,找到变量var a = 1,js解析器只会读取等号前面的var a,并把a设置值未定义,并不会读取等号后面的a = 1,所以a的值是未定义,并加入仓库,根据function找到函数后,function a (){ alert(2); },找到函数是函数整体,这是js的预解析(预解析只找var 和函数)。遇到重名的留下后面的,变量和函数重名了,函数在后面,只留下函数。
    正式读取代码的时候,是从上到下从左到右,上面<script/>块中定义的变量可以直接在下面的<script/>中使用。
    alert(a);
    var a = 1;
    读取到alert(a);时候,因为之前a是未定义,所以这个报错,遇到表达式a = 1,就把之前a是未定义变成1。
    
    
    
    
    
    
    var a = 1;
    function fn1(){
        alert(a);
        var a = 2;
    }
    fn1();
    alert(a);
    首先预解析找到var a = 1,此时a未定义,和函数,加入仓库(预解析只解析var 和 函数的定义)。
    预解析完了,从上到下执行,遇到函数调用fn1(); 函数是一个局部的域,会新开一个局部作用域,遇到域就进行预解析和逐行执行代码,局部预解析时var a 是未定义,局部预解析完了就开始逐行执行代码,alert(a)只会在函数局部域内找a是未定义,var a = 2只是改变局部域中a为2不会改变全局域的a,最后alert(a)弹出1
    
    
    
    
    
    
    var a = 1;
    function fn1(){
        alert(a);    
        a = 2;
    }
    fn1();
    alert(a);
    首先预解析,a是未定义,函数fn1也加入仓库,全局域的预解析完了。下面开始逐行执行代码。var a = 1把仓库中的a改成1,找到函数的定义,这里不动它,然后找到函数的调用fn1(),开始函数局部域的预解析,局部域中没有var 和函数定义,局部域的预解析完了,然后逐行执行函数内部,读到alert(a),在局部域中没有找到a,则会向上级域中去找,找到全局域的a = 1,弹出a = 1,在执行a = 2,局部作用域没有a则找到上级域,把a改成了2,最后弹出2.
    
    
    
    
    
    var a = 1;
    function fn1(a){
        alert(a);    //a是局部域中的仓库中的a,相当于写了var a;
        a = 2;
    }
    fn1();
    alert(a);
    首先预解析var a = 未定义 ,和函数fn1()加入仓库。
    逐行执行代码a = 1,函数调用fn1(),看到参数a,会在函数局部作用域解析a = 未定义,alert(a)弹出未定义,a= 2改变局部作用域中的a的值,最后alert(a),弹出1。
    
    
    
    
    
    
    
    var a = 1;
    function fn1(a){
        alert(a);//a是局部域中的仓库中的a,相当于写了var a = 1;
        a = 2;
    }
    fn1(a);
    alert(a);
    全部预解析,a=未定义,函数就是一个函数。
    读代码,全局a=1,函数定义不动。函数调用,局部开始新的预解析和逐行读代码,局部没有var 没有function,有参数a,加入局部域的仓库a = 未定义,接下来局部域逐行读代码,首先从参数开始读,a= 1,是从全局前面传进来的,局部作用域的a等于1了,alert(a)弹出1,a=2修改局部作用域的a =  2,全局a没有改变,因为a参数传进来相当于局部域定义了一个新变量a,最后弹出1
    
    
    
    
    
    
    function fn2(){
        var a = '9999999克拉钻石23456789';
        fn3(a);
    }
    fn2();
    
    function fn3(a){
        alert(a); //相当于写了var a = '99923456678';
    }
    全局解析:把函数fn2()和fn3()加入全局的仓库。
    逐行读代码: fn2()调用:
                 局部解析 var a = 未定义,无函数定义
                 局部逐行读代码,a = '9999999克拉钻石23456789',函数调用fn3(a),局部域仓库中没有找到fn3()的定义,去全局域中找,找到了,fn3(a)调用开始:
                               局部的局部解析,参数相当于新定义一个局部变量,a = 未定义
                               局部的局部逐行执行代码,a = 全局传进来的值9999999克拉钻石23456789,alert(a)
                 
    <!DOCTYPE HTML>
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>无标题文档</title>
    
    <script>
    window.onload = function (){
        var aBtn = document.getElementsByTagName('input');
        for( var i=0; i<aBtn.length; i++ ){
            aBtn[i].onclick = function (){
                alert( i );            // 一直是3,因为for执行完之后i一直等于3
                //aBtn[i].style.background = 'yellow';
                for( var i=0; i<aBtn.length; i++ ){
                    aBtn[i].style.background = 'yellow';
                }
            };
        }
    };
    </script>
    
    </head>
    
    <body>
    
    <input type="button" value="按钮1" />
    <input type="button" value="按钮2" />
    <input type="button" value="按钮3" />
    
    </body>
    </html>
    全局预处理和执行:
    创建全局LexicalEnvironment === window对象,保存全局var 和函数的定义(保存函数名作为变量指向函数),
        var f = 5;
        g = 6;
        function xx(){};
        window对象{
             f : 未定义
             xx : 指向函数
        }
        g前面没有var ,预处理阶段不会保存到window对象,会报错。
    
    
    alert(f);//弹出函数体
    var f = 5;
    function f(){};
    ---------------------------
    alert(f);//还是函数体
    function f(){};
    var f = 5;
    
    有冲突时后面出现的是函数,则覆盖前面的变量,如果后面出现的是变量,则不能覆盖前面的函数,后面的函数覆盖前面的函数是重新赋值,后面的变量覆盖前面的变量也是重新赋值。
    alert(f);//弹出后面的
    function f(){alert(2)};
    function f(){alert(1)};
    
    alert(f1);//undefined
    var f1 = 5;
    var f1 = 6;

    var f1=5;
    var f2=6;
    alert(f2);//6 alert(f2);
    //弹出后面 var f2 = 5; function f2(){alert(1)}; alert(f3);//弹出前面 function f3(){alert(1)}; var f3 = 5; alert(f4);//弹出后面函数 function f4(){alert(1)}; var f4 = 5; function f4(){alert(2)}; --------------------------------------------- alert(a);//undefined alert(b);//预处理阶段,b前面没有var,不会加入到Window对象中,报错 alert(f);//函数体 alert(g);//undefined var a = 5;//执行阶段window对象中a : 5 b = 6;//预处理阶段没有将b加入windown对象中,但是在执行阶段会将加入b : 6到window对象 alert(b);//弹出6 function f(){ console.log('f'); } var g = function (){ console.log('g'); } alert(g);//弹出函数体 预处理阶段,window对象 window{ a : undefied f : 指向函数 g : undefined ////预处理阶段只会保存 g : undefined,后面函数不是声明方式的函数,不会保存在window对象中。 } 执行阶段 window{ a: 5 b :6 f:指向函数 g :指向函数 }
    函数预处理和执行:
    function f(a,b,c){//参数传递相当于在函数体写了 var a = 1,var b = 2,
        alert(a);//弹出函数体
        alert(b);//2
        
        var b = 100;
        function a(){
        }
    }
    f(1,2);
    
    函数局部预解析过程中:
    局部
    {
      a : 1   //局部作用域的a  ,不影响全局作用域的a,
      b : 2   //局部作用域的b  ,不影响全局作用域的b,
      c : undefined
      arguments : 
    }
    执行过程中
    {
      a : 执行函数的引用   //冲突覆盖变量
      b:2   //变量不会覆盖
      c : undefined
    }
    
    -------------------------------------------
    function f1(){
        function f2(){
          b = 100;//函数体中没有通过var声明的变量,会加入到全局window作用域中,window{ b : 10},不是加入到f2和f1函数的局部作用域中,
        }
        f2();
    }
    f1();
  • 相关阅读:
    [三]JavaIO之IO体系类整体设计思路 流的概念以及四大基础分类
    [二] JavaIO之File详解 以及FileSystem WinNTFileSystem简介
    [一]FileDescriptor文件描述符 标准输入输出错误 文件描述符
    [零] JavaIO入门简介 程序设计语言 为什么需要IO库
    装饰器模式 Decorator 结构型 设计模式 (十)
    适配器模式 adapter 结构型 设计模式(九)
    layui 鼠标悬停单元格显示全部
    mysql 日期总结
    区域块路由与全局路由兼容,双重路由
    JS-SDK相关参考
  • 原文地址:https://www.cnblogs.com/yaowen/p/6828949.html
Copyright © 2020-2023  润新知