zoukankan      html  css  js  c++  java
  • js代码执行过程

      当浏览器加载了js代码之后,发生什么?js引擎怎么工作?编译器做了什么?

      以及执行环境对象、作用域链、活动对象、变量对象 是什么?

      以及作用域链什么时候创建、销毁?等等,这些对象的生命周期都会在js代码执行过程得到一一的体现

     先粗浅地了解下流程:

    <script src='app.js'></script>
    <script>
        var name = "Tom";
    
        function getInfo(){
            return name;
        }
    
        getInfo();
    </script>
    <script>
        var sex = 'male';
    </script>

      1. 浏览器载入第一个代码段后,开始进行语法检测(书写是否正确等);之后,如果还有代码段,继续载入,语法检查;直到没有了代码段;

      2. js引擎 创建全局执行环境,同时生成作用域链、变量对象;将全局执行对象栈入环境栈中;(在浏览器中全局执行对象为window;全局执行环境在退出程序时销毁;)

      3. 编译器开始对全局执行环境中的var/function声明进行预解析;如果全局执行环境的变量对象中没有name、getInfo等,就添加它们

      4. 编译器预解析后,生成代码;js引擎开始执行代码;

    以上几个步骤是非常粗浅的,省却了很多细节,但是js代码从加载到浏览器到执行完,基本就是这个过程;

    下面结合代码、图表、解释等重新、详细地讲解下js代码的执行过程,这里举两个例子,一个是基本简单的流程,一个则涉及到闭包;

    一个基本简单的例子:

    var name = "Tom";
    
    function getInfo(){
    
        var nation = "China";
    
        return name + nation;
    
    }
    
    getInfo();

      1. 编译器进行语法检测

      2. js引擎创建全局执行环境对象window,此时生成作用域链scope1,变量对象

      

      3. 编译器 对 var/function 声明的变量、函数预处理;将声明的变量name添加到变量对象中,值为undefined;

       function声明的函数变量添加到变量对象中,同时将作用域链scope1保存在[[scope]]属性中;

         同时,将全局执行环境栈入环境栈中;

      

        注1:函数的作用域链在函数声明时就已经创建,保存在内部属性[[scope]]中;在函数调用的时候会再次创建作用域链,用于延伸;

        注2:此时编译器没有对getInfo函数体做任何操作,

        注3:对var/function声明的变量预处理时,涉及到声明提前,函数声明优先的规则

        这一步处理完之后的代码相当于:

     1 function getInfo(){
     2     // 编译器此时没有对函数体中操作;
     3     // 只有函数被调用时,编译器才会处理函数体
     4     var nation = "China";
     5 
     6     return name + nation;
     7 
     8 }
     9 
    10 var name;
    11 
    12 name = "Tom";
    13 
    14 getInfo();    

      4. 编译器生成代码,js引擎开始执行代码

        4.1 代码执行到12行时,js引擎 找到环境栈中顶部执行对象, 然后根据作用域链查找变量对象,发现变量对象中存在name,则赋值name="Tom"

        4.2 代码执行到14行时,js引擎调用getInfo函数

          4.2.1 创建getInfo执行环境,同时生成作用域链,活动对象;

              此时生成的作用域链会将函数[[scope]]保存的scope1复制过来,再添加上新生成的getInfo活动对象;

              活动对象在生成时,会生成arguments对象;

              注:变量对象、活动对象区别

                                        变量对象:在生成全局执行环境时生成,不包含arguments

              活动对象:在调用函数,生成函数执行环境时生成,包含arguments对象

                                        讲述到现在一直没有出现作用域的概念,本人认为变量对象、活动对象就可以看成作用域;

          4.2.2 将getInfo执行环境对象栈入环境栈中,编译器开始对 var/function声明的变量预解析

             

            预解析后,相当于下面的代码:

     1 function getInfo(){
     2    
     3     var nation;
     4 
     5     nation = "China";
     6 
     7     return name + nation;
     8 
     9 }
    10 
    11 var name;
    12 
    13 name = "Tom";
    14 
    15 getInfo();

          4.2.3 编译器生成代码,js引擎开始执行

            4.2.3.1 执行到第5行,通过作用域链找到nation,然后赋值;

                                 4.2.3.2 执行到第7行, 通过作用域链找到name,然后返回值

                                 4.2.3.3 函数执行完,销毁getInfo活动对象、作用域链,将getInfo执行环境栈出,销毁;控制权交给环境栈中最顶部的执行环境;

    基本简单的流程就是这样,如果有闭包,即使没有调用闭包,闭包[[scope]]指向的作用域链涉及的变量对象、活动对象不会销毁;

    一个闭包相关的流程:

    var name = "Tom";
    
    function getInfo(){
    
        var nation = "China";
    
        function sumIn(){
            return name + nation;
        }
    
        return sumIn();
    }
    
    getInfo();

    一个相对复杂的流程:

    var name="Hello World";
    var obj = {
        name:'obj Object',
    
        getName:function(){
    
            console.log( name );
    
            console.log(this.name);
    
        }
    }
    obj.getName();

     明晰这个流程,必须对作用域链非常了解;作用域链只与函数相关,跟对象无关;

      

        

  • 相关阅读:
    Lombok介绍、使用方法和总结
    JSONObject.fromObject
    idea多级目录不展开的问题
    SpringBoot | 查看默认版本配置
    常见的版本号及Springcloud的版本
    Spring Boot,Spring Security实现OAuth2 + JWT认证
    OAuth2实现原理
    什么是OAuth2
    springboot 实时监控 spring-boot-starter-actuator 包
    解决springboot 新版本 2.1.6 spring-boot-starter-actuator 访问报404
  • 原文地址:https://www.cnblogs.com/RocketV2/p/5812995.html
Copyright © 2011-2022 走看看