`
编程足球
  • 浏览: 257877 次
  • 性别: 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-Canvas-to-Blob-master

    如果目标浏览器不支持原生的`toBlob`方法,JavaScript-Canvas-to-Blob-master将自动处理这个过程,保证在所有现代浏览器及部分旧版浏览器中的兼容性。这极大地扩展了开发者在跨平台Web应用中使用Canvas的能力,尤其...

    org.mozilla.javascript-1.7.2.jar.zip

    4. 教育与学习:Rhino作为JavaScript的实现,对于学习和理解JavaScript的底层机制非常有帮助,开发者可以通过阅读源代码,深入了解JavaScript的执行过程。 总结,"org.mozilla.javascript-1.7.2.jar.zip"是Mozilla ...

    原生js ---- 二维码解析器和移动端长按识别二位码demo

    "原生js ---- 二维码解析器和移动端长按识别二位码demo"这个项目是关于如何使用JavaScript来实现二维码的解析和在移动端设备上的长按识别功能。下面我们将详细探讨相关的知识点。 首先,`qrcode.js`是一个流行的...

    C# 动态解析 javascript 脚本引擎源码

    开发者可以通过阅读这些源码来了解C#如何实现JavaScript引擎的核心功能,包括词法分析、语法解析、抽象语法树(AST)的构建以及代码的执行。 6. **Tests**:测试目录,通常包含单元测试或集成测试,用于验证Noesis....

    Node.js-用JS解析SPF(senderpolicyframework)记录

    标题中的“Node.js-用JS解析SPF(senderpolicyframework)记录”表明我们将探讨如何使用JavaScript在Node.js环境中解析SPF(Sender Policy Framework)记录。SPF是一种DNS TXT记录,用于防止电子邮件伪造,确保发送...

    javascript经典特效---显示人口数量.rar

    2. **数据解析**:收到服务器返回的数据后,JavaScript需要解析它。如果是JSON格式,可以使用`JSON.parse()`方法将其转化为JavaScript对象。 3. **事件驱动**:可能有用户交互触发人口数量的更新,例如点击按钮。...

    JavaScript 语言在引擎级别的执行过程--周爱民

    总的来说,JavaScript在引擎级别的执行过程涉及到了复杂的解析、编译和执行步骤,以及高效的内存管理和异步模型。开发者了解这些知识,不仅可以写出更优的代码,还能对调试和优化问题提供有力的支持。

    how-javascript-works.zip

    2. **作用域创建**:在解析过程中,浏览器会创建作用域链,确定变量的可见性和生命周期。 3. **执行上下文**:JavaScript代码在特定的执行上下文中运行,分为全局执行上下文和函数执行上下文。 4. **内存管理**:...

    Pro-Android-Web-Apps-Developing-HTML5-JavaScript-CSS-and-Chrome-OS-Web-Apps.pd

    - **附录:调试Android Web应用**:提供了具体的调试技巧和工具,帮助开发者解决开发过程中遇到的问题。 综上所述,《Pro-Android Web Apps》这本书不仅是一本全面覆盖HTML5、CSS3和JavaScript等关键技术的指南,...

    zh.javascript.info-master.zip

    在JavaScript的世界里,"JavaScriptCore"是苹果WebKit引擎的一部分,它负责解析和执行JavaScript代码。这个标签暗示了教程可能涵盖了JavaScript的基础到核心机制,如变量、数据类型、作用域、函数、对象、闭包等,...

    javascript经典特效---HTML代码的预览.rar

    总之,“javascript经典特效---HTML代码的预览.rar”提供的示例很可能是一个完整的解决方案,涵盖了从获取和解析HTML代码,到实时渲染预览,再到用户交互响应的全过程。学习并理解这个例子,对于提升JavaScript技能...

    前端项目-themoviedb-javascript-library.zip

    《前端项目:themoviedb-javascript-library的深入解析》 在现代Web开发中,前端项目的构建离不开高效、便捷的库和API的辅助。本文将详细介绍一个名为"themoviedb-javascript-library"的前端项目,它是一个专门用于...

    javascript经典特效---用户认证的选择.rar

    JavaScript可以用来生成和解析JWT,用于用户会话管理。 6. **OAuth和OpenID Connect**:这些是第三方认证的标准协议,JavaScript可以用来集成这些服务,让用户通过社交账号(如Google或Facebook)登录。 7. **本地...

    javascript经典特效---友人信息搜索器.rar

    JavaScript提供了内置的`JSON.parse()`和`JSON.stringify()`方法用于解析和序列化JSON数据。 5. **正则表达式**: - 正则表达式用于匹配关键词,实现模糊搜索。通过创建合适的正则表达式,我们可以检查友人信息中...

    dhtml-html-css-javascript-dom帮助文档(.chm)五合一

    4. **JavaScript**:涉及变量、数据类型、函数、面向对象编程、DOM操作、AJAX等核心概念,以及一些常见的库和框架如jQuery、React等的使用。 5. **DOM**:解释DOM结构,如何通过JavaScript操作DOM节点,实现动态...

    Regulex-JavaScript正则表达式解析和可视化工具

    Regulex是一款强大的JavaScript工具,专门用于正则表达式的解析和可视化。在IT行业中,正则表达式(Regular Expression)是一种强大的文本处理工具,广泛应用于数据验证、搜索、替换等场景。然而,由于其语法复杂,...

    Node.js-parse-class解析hyperscript类符号

    `parse-class`库的核心功能是将字符串形式的类列表转换为JavaScript对象,便于进一步操作。例如,给定一个字符串如`'foo bar baz'`,`parse-class`会将其解析为`{foo: true, bar: true, baz: true}`。这样,开发者...

    javascript经典特效---时间警告器.rar

    而JavaScript则负责页面的动态行为,即时间警告器的核心功能。 在实际应用中,时间警告器还可以结合其他技术,如AJAX实现自动刷新,以便在不刷新整个页面的情况下获取最新时间信息。此外,考虑到不同时区的用户,还...

    Javascript - The Web Warrior Series 6th Edition

    ### JavaScript - The Web Warrior Series 6th Edition ...通过系统学习本书,读者不仅可以掌握JavaScript的核心知识,还能了解最新的开发趋势和技术动态,为成为一名优秀的Web开发者打下坚实的基础。

Global site tag (gtag.js) - Google Analytics