执行上下文与作用域链最清晰的讲解

事先学习执行上下文与作用域前,先了解下面几个名词:

执行上下文:决定变量及函数可以访问的数据行为

变量对象:存储了一个上下文中定义的所有变量及函数

作用域链:决定各级上下文中的代码在访问变量及函数时的顺序

上下文执行栈:控制程序执行流

同学们可以大胆的假设一下这几个名词之间的联系。

执行上下文的概念在Javascript中是颇为重要的。全局上下文是最外层的上下文,在浏览器中就是我们常说的Window对象。每个函数调用都有自己的上下文。上下文在其所有代码执行完毕后会被销毁包括定义在它上面的所有变量及函数(全局上下文在其应用程序退出前才会被销毁,例如关闭网页或者退出浏览器)。

变量对象是与执行上下文相关联的,每一个上下文都有自己的变量对象。例如,一个函数Test中包含两个传入的参数num与sum,那么在这个函数的上下文中,其活动对象arguments也就是num与sum两个参数就是该上下文的变量对象。

作用域链将各级上下文的变量对象串联起来,决定了上下文中的代码访问变量对象的顺序,当前正在执行的上下文的变量对象总是在作用域的最前端。作用域链中的下一个变量对象来自包含当前执行的上下文的下一个上下文。

上下文执行栈中存储的是当前正在需要运行的函数的上下文,当函数执行完毕该上下文会被弹出。

看下面的例子分析每个函数的作用域链,说出每个函数能够调用到的函数:

var globalData = "last"
function scopeChain1(){
    let level1 = "first";
    let globalData = "first"
    console.log(globalData );
    function scopeChain2(){
        let level2 = "second";  
    }
}

解析:scopeChain1函数上下文中的作用域链有两个变量对象,分别是位于作用域链最前端的scopeChain1的变量对象,以及后面的全局上下文中的变量对象,执行函数scopeChain1,控制台会输出”first“,原因是,代码执行时的标识符解析会沿着作用域链进行搜索,搜索过程始终中在作用域链最前端开始,搜索到了即完成,若没有搜索到标识符通常会报错。

值得注意的是只有函数声明会被包含在变量对象里面,而函数表达式并不会。

scopeChain2函数上下文的作用域链分别是scopeChain2变量对象,scopeChain1上下文的变量对象,全局上下文的变量对象。

执行上下文主要有全局执行上下文和函数执行上下文(eval是第三种上下文),还有其它方式来增强作用域链,那就是with与try、catch。with的使用不知道大家有没有了解过,不常用,不推荐使用,因为会影响性能并且难以调试。catch会创建一个新的变量对象,变量对象中是错误代码的声明。

with介绍:例如当一段代码中频繁使用一个对象中的属性,那么可以使用with在代码外使用该对象进行包裹,那么这段代码就会更新一个新的作用域,也就是该对象,代码内的取值都会优先在该对象内搜索,也就是生成了一个新的变量对象在作用域链的前端。

你可能感兴趣的:(JavaScript,javascript,前端)