`
编程足球
  • 浏览: 251583 次
  • 性别: Icon_minigender_1
  • 来自: 福州
社区版块
存档分类
最新评论

javascript核心 -- 解析过程

 
阅读更多
1.javascript解析过程
如果一个文档流中包含多个script代码段(用script标签分隔的js代码或引入的js文件),它们的运行顺序是:
步骤1. 读入第一个代码段(js执行引擎并非一行一行地执行程序,而是一段一段地分析执行的)
步骤2. 做语法分析,有错则报语法错误(比如括号不匹配等),并跳转到步骤5
步骤3. 对var变量和function定义做“预解析”(永远不会报错的,因为只解析正确的声明)
步骤4. 执行代码段,有错则报错(比如变量未定义)
步骤5. 如果还有下一个代码段,则读入下一个代码段,重复步骤2
步骤6. 结束


javascript解析模拟
1. 待解析的js
/*全局(window)域下的一段代码*/
var i = 1,j = 2,k = 3;
function a(o,p,x,q){
    var x = 4;
    alert(i);

    // 在函数a中定义新的函数b,并且有变量i,y
    function b(r,s) {
        var i = 11,y = 5;
        alert(i);
        
       //在函数b中定义新的函数c,并且有变量z
       function c(t){
           var z = 6;
           alert(i);
        };
        
       //在b中定义 函数表达式 d
        var d = function(){
            alert(y);
        };
        c(60);
        d();
    };
    b(40,50);
}
a(10,20,30);




2. 建立分析树
上面的代码很简单,就是先定义了一些全局变量和全局方法,接着在方法内再定义局部变量和局部方法,现在JS解释器读入这段代码开始解析,前面提到 JS 引擎会先通过语法分析和预解析得到语法分析树,至于语法分析树长什么样儿,都有些什么信息。

下面我们以一种简单的结构:一个 JS 对象(为了清晰表示个各种对象间的引用关系,这里的只是伪对象表示,可能无法运行)来描述语法分析树(这是我们比较熟悉的,实际结构我们不去深究,肯定复杂得多,这里是为了帮助理解解析过程而特意简化)。
/**
* 模拟建立一棵语法分析树,存储function内的变量和方法
*/
var SyntaxTree = {
        // 全局对象在语法分析树中的表示
    window: {
        variables:{
            i:{ value:1},
            j:{ value:2},
            k:{ value:3}
        },
        functions:{
            a: this.a
        }
    },
 
    a:{
        variables:{
            x:'undefined'
        },
        functions:{
            b: this.b
        },
        scope: this.window
    },
 
    b:{
        variables:{
            y:'undefined'
        },
        functions:{
            c: this.c,
            d: this.d
        },
        scope: this.a
    },
 
    c:{
        variables:{
            z:'undefined'
        },
        functions:{},
        scope: this.b
    },
 
    d:{
        variables:{},
        functions:{},
        scope: {
           myname:d,
           scope: this.b
        }
    }
};


上面就是关于语法分析树的一个简单表示,正如我们前面分析的,语法分析树主要记录了每个 function 中的变量集(variables),方法集(functions)和作用域(scope)。

语法分析树关键点
变量集(variables)中,只有变量定义,没有变量值,这时候的变量值全部为“undefined”
作用域(scope),根据词法作用域的特点,这个时候每个变量的作用域就已经明确了,而不会随执行时的环境而改变。【什么意思呢?就是我们经常将一个方法 return 回去,然后在另外一个方法中去执行,执行时,方法中变量的作用域是按照方法定义时的作用域走。其实这里想表达的意思就是不管你在多么复杂,多么远的地方执行该方法,最终判断方法中变量能否被访问还是得回到方法定义时的地方查证】
作用域(scope)建立规则:
    a.对于函数声明和匿名函数表达式来说,[scope]就是它创建时的作用域
    b.对于有名字的函数表达式,[scope]顶端是一个新的JS对象(也就是继承了Object.prototype),这个对象有两个属性,第一个是自身的名称,第二个是定义的作用域,第一个函数名称是为了确保函数内部的代码可以无误地访问自己的函数名进行递归。

3、执行环境
语法分析完成,开始执行代码。我们调用每一个方法的时候,JS 引擎都会自动为其建立一个执行环境和一个活动对象,它们和方法实例的生命周期保持一致,为方法执行提供必要的执行支持,针对上面的几个方法,我们这里统一为其建立了活动对象(按道理是在执行方法的时候才会生成活动对象,为了便于演示,这里一下子定义了所有方法的活动对象),具体如下:
/**
* 执行环境:函数执行时创建的执行环境
*/
var ExecutionContext = {
    window: {
        type: 'global',
        name: 'global',
        body: ActiveObject.window
    },
 
    a:{
        type: 'function',
        name: 'a',
        body: ActiveObject.a,
        scopeChain: this.window.body
    },
 
    b:{
        type: 'function',
        name: 'b',
        body: ActiveObject.b,
        scopeChain: this.a.body
    },
 
    c:{
        type: 'function',
        name: 'c',
        body: ActiveObject.c,
        scopeChain: this.b.body
    },
 
    d:{
        type: 'function',
        name: 'd',
        body: ActiveObject.d,
        scopeChain: this.b.body
    }
}

上面每一个方法的执行环境都存储了相应方法的类型(function)、方法名称(funcName)、活动对象(ActiveObject)、作用域链(scopeChain)等信息,其关键点如下:

body属性,直接指向当前方法的活动对象
scopeChain属性,作用域链,它是一个链表结构,根据语法分析树中当前方法对应的scope属性,它指向scope对应的方法的活动对象(ActivceObject),变量查找就是跟着这条链条查找的

4. 活动对象
/**
* 活动对象:函数执行时创建的活动对象列表
*/
var ActiveObject = {
        window: {
        variables:{
            i: { value:1},
            j: { value:2},
            k: { value:3}
        },
        functions:{
            a: this.a
        }
    },
 
    a:{
        variables:{
            x: {value:4}
        },
        functions:{
            b: SyntaxTree.b
        },
        parameters:{
            o: {value: 10},
            p: {value: 20},
            x: this.variables.x,
            q: 'undefined'
        },
        arguments:[this.parameters.o,this.parameters.p,this.parameters.x]
    },
 
    b:{
        variables:{
            y:{ value:5}
        },
        functions:{
            c: SyntaxTree.c,
            d: SyntaxTree.d
        },
        parameters:{
            r:{value:40},
            s:{value:50}
        },
        arguments:[this.parameters.r,this.parameters.s]
    },
 
    c:{
        variables:{
            z:{ value:6}
        },
        functions:{},
        parameters:{
            u:{value:70}
        },
        arguments:[this.parameters.u]
    },
 
    d:{
        variables:{},
        functions:{},
        parameters:{},
        arguments:[]
    }
}

上面每一个活动对象都存储了相应方法的内部变量集(variables)、内嵌函数集(functions)、形参(parameters)、实参(arguments)等执行所需信息,活动对象关键点

创建活动对象,从语法分析树复制方法的内部变量集(variables)和内嵌函数集(functions)
方法开始执行,活动对象里的内部变量集全部被重置为 undefined
创建形参(parameters)和实参(arguments)对象,同名的实参,形参和变量之间是【引用】关系
执行方法内的赋值语句,这才会对变量集中的变量进行赋值处理
变量查找规则是首先在当前执行环境的 ActiveObject 中寻找,没找到,则顺着执行环境中属性 ScopeChain 指向的 ActiveObject 中寻找,一直到 Global Object(window)
方法执行完成后,内部变量值不会被重置,至于变量什么时候被销毁,请参考下面一条
方法内变量的生存周期取决于方法实例是否存在活动引用,如没有就销毁活动对象
6和7 是使闭包能访问到外部变量的根本原因


以上内容多数转载至网络,非个人原创.
分享到:
评论

相关推荐

    基于JavaScript的视频后台管理系统源码+项目说明(前端大作业).zip

    * 发布过程:环境部署 -> 代码部署 -> nginx配置 -> 域名解析 【备注】:后端采用训练营提供的轻服务 # 2. 功能介绍 主要包含直播间管理,短视频管理,评论管理三部分。 | 模块 | 功能 | 完成情况 | 可扩展的点 ...

    vue数据双向绑定的实现与原理解析(核心完整代码)

    先声明,该代码是网上一位大佬提供的,但是学习它的代码过程中...该压缩文件内容是vue数据双向绑定的实现与原理解析,提供核心完整代码,并有我的代码注释,浅显易懂,但是需要es6的学习和有一定的javascript基础才行。

    frontend:前端学习总结

    前端知识学习记录 记录每天利用碎片时间学习...《极客时间--JavaScript核心原理解析》(ps:难度较高,需要结合最新ECMAScript规范理解) 网络 书籍 《HTTP权威指南》 《图解HTTP》 语音/视频课程 《极客时间--趣谈网络

    javascript学习笔记.docx

    3) 脚本执行过程是Web浏览器的HTML解析过程的一部分。脚本按照它们的出现顺序执行。 4) 简单的对话框可用:alert()、 confirm()、 prompt()之一。 5) 时间间隔方法为: setInterval()、 cleraInterval() 。 ...

    Selenium介绍及原理解析.docx

    Selenium是ThoughtWorks公司的一个强大的开源Web功能测试工具系列,采用Javascript来管理整个测试过程,包括读入测试套 件、执行测试和记录测试结果。它采用Javascript单元测试工具JSUnit为核心,模拟真实用户操作,...

    JavaScript数据交互实战应用

    Javascript数据交互是JS知识点的核心部分,可以稍微片面的说,不会JS数据交互,等于不会Javascript,可见学习这门课程的重要性。 忠彬老师主讲的《JS数据交互实战应用》课程,既适合新学员掌握相关的知识,还有益于...

    snoics-reptile 网页爬虫2.0

    1、snoics-reptile是什么?... 核心代码全部重写,增加了扩展性,通过扩展之后,基本上能实现对整个网站完整的解析 1.0: 实现了整站抓取的基本的功能,不能解析特殊的URL,对javascript无法辨认

    彩蛋篇:CDN 的缓存与回源机制解析(1).md

    我们现在站在性能优化的角度,一起简单地复习一遍这个经典的过程:首先我们需要通过 DNS(域名解析系统)将 URL 解析为对应的 IP 地址,然后与这个 IP 地址确定的那台服务器建立起 TCP 网络连接,随后我们向服务端抛...

    JSON 核心技术应用

    XML 如何拥有跨平台,跨语言的优势,然而,除非应用于 Web Services,否则,在普通的 Web 应用中,开发者经常为 XML 的解析伤透了脑筋,无论是服务器端生成或处理 XML,还是客户端用 JavaScript 解析 XML,都常常...

    使用js实现的停车场管理系统的设计与实现【尚学堂·百战程序员】.zip

    本书以停车场管理系统为例,结合实际项目开发,详细介绍了如何使用JavaScript语言进行系统设计与实现的过程。 ### 内容特点: 1. **系统设计思路**:本书首先介绍了停车场管理系统的需求分析和系统设计思路,包括...

    前端面试八股文-超详细的前端基础知识的应用与技巧

    内容概要:本资源提供了一系列精心挑选的前端面试题,旨在帮助广大前端开发者系统复习和巩固基础知识,深入理解前端技术栈,以及提升解决实际问题的能力。题目涵盖了HTML、CSS、...可以在学习过程中进行笔记整理

    javascript入门笔记

    4、1997年 网景 将Javascript 1.1 提供给了ECMA(欧洲计算机制造商联合会),ECMA 获取了 JS 的核心,称之为 ECMA Script (ES) 完整的JS组成: 1、核心(ES) 2、文档对象模型(Document Object Model) - DOM 允许让 ...

    asp.net知识库

    SQL过程自动C#封装,支持从表到基本存储过程生成 使用SQLDMO控制 SQL Server 使用SQL-DMO实现定制SQL Scripts Create Tables and Build inserts from Tables by using Mygeneration Templates(Sql Server) C# 获取...

    ByteDance-2021-FE-Trainingcamp:字节跳动2021.2 训练营[我和我的抖音]前端专场大作业,本仓库为视频后台管理系统

    项目分析1.1 视频后台管理核心需求直播间管理:新建/编辑直播间、查看直播间、删除直播间短视频管理:发布/编辑短视频、查看短视频、删除短视频评论管理:直播间评论列表、评论详情,删除评论用户管理:管理员登录...

    skulpt:Skulpt是Python编程语言的Javascript实现

    欢迎来到Skulpt Skulpt是Python 2.x的Javascript实现。 在您的浏览器中运行的Python! 在您的iPad上运行的Python! 它被用于多个项目,包括《 -您可以在那里看到速写。 尝试以了解Skulpt的实际效果。起源Skulpt是...

    应用篇 1:优化首屏体验——Lazy-Load 初探(2).md

    我们现在站在性能优化的角度,一起简单地复习一遍这个经典的过程:首先我们需要通过 DNS(域名解析系统)将 URL 解析为对应的 IP 地址,然后与这个 IP 地址确定的那台服务器建立起 TCP 网络连接,随后我们向服务端抛...

    translationCore-PoC:专门为隐喻制作的翻译核心POC

    不仅要一次检查所有要考虑的事物,还要一次检查一种类型,遍历整本圣经……这是检查过程的关键。 这将提供可量化和可测量的翻译输出质量。 所有检查工具都是从为每节经文准备的翻译注释中提取的,以确保翻译时翻译...

    存储篇 1:浏览器缓存机制介绍与缓存策略剖析(1).md

    我们现在站在性能优化的角度,一起简单地复习一遍这个经典的过程:首先我们需要通过 DNS(域名解析系统)将 URL 解析为对应的 IP 地址,然后与这个 IP 地址确定的那台服务器建立起 TCP 网络连接,随后我们向服务端抛...

    前方的路:希望以此为你的起点.md

    我们现在站在性能优化的角度,一起简单地复习一遍这个经典的过程:首先我们需要通过 DNS(域名解析系统)将 URL 解析为对应的 IP 地址,然后与这个 IP 地址确定的那台服务器建立起 TCP 网络连接,随后我们向服务端抛...

Global site tag (gtag.js) - Google Analytics