JavaScript中的执行上下文及调用堆栈

执行上下文.png

一、执行上下文是什么

代码运行是在一定的环境之中运行的,这个运行环境我们就成为执行环境,也就是执行上下文,按照执行环境不同,我们可以分为三类:
全局执行环境:代码首次执行时候的默认环境
函数执行环境:每当执行流程进入到一个函数体内部的时候
Eval执行环境:当eval函数内部的文本执行的时候

二、执行上下文栈是什么

既然是‘栈’,那就得符合‘栈’的特性,即数据结构是先进后出。下面我们看一段代码:

function cat(a){
    if(a<0){
        return false;
    }
    console.log('入栈:'+a);
    cat(a-1);
    console.log('出栈:'+a);
}
cat(3);
// 入栈:3
// 入栈:2
// 入栈:1
// 入栈:0
// 出栈:0
// 出栈:1
// 出栈:2
// 出栈:3

我们来分析上面的代码的执行过程:
①浏览器加载时,程序进入全局执行上下文,将其压入一个栈内(第一个进入的,所以最底层);该执行上下文下只有一个函数cat、cat调用、参数3;
②程序进入cat函数内,即进入该函数执行上下文,也将其压入栈内(第二个进入的,所以倒数第二层),因为参数为3大于0,继续往下执行,输出'入栈:3';
③程序继续执行,调用函数cat,再次进入新的函数执行上下文,继续压入栈内(第三个进入,倒数第三层),参数为a-1,循环②步骤;这里,需要注意的是,因为调用了函数cat(a-1),导致下一行代码'出栈:a'(此时a仍为3),也就是'出栈:3'暂时搁浅起来,存在栈内倒数第二层
④不断重复②③步骤,以次输出'入栈:2'、'入栈:1'、'入栈:0';同时被搁浅的有'出栈:2'(栈内倒数第三层)、'出栈:1(栈内倒数第四层)'、'出栈:0(栈内倒数第五层)';
⑤按照栈的特性,被搁浅起来的4个输出项:以次输出'入栈:3'、'入栈:2'、'入栈:1'、'入栈:0';
以上就是执行上下文栈的具体情况,请大家手动代码练习一下,相信会容易理解透彻。


堆栈.png

三、执行上下文栈的过程细节

我们已经知道,每次调用函数都会执行一个新的上下文,每个执行上下文都分为两个阶段:创建阶段、执行阶段
创建阶段:指的是程序调用函数,但代码未执行时的阶段;
执行阶段:指的是变量分配、函数执行等代码执行阶段;

(一)创建阶段
该阶段会调用函数数时,创建一个执行上下文对象(executionContextObj),该对象又包含了三个对象,分别是作用域链对象(scopeChain)、变量对象(variableObject,简称VO)、this对象,其中VO包括变量声明(variable)、函数声明(function)、参数(arguments)等。
这三个对象分别是在三个步骤创建的:
步骤1:初始化作用域链(scopeChain),开辟栈内存
步骤2:创建参数、函数、变量
步骤3:决定上下文的'this'的值
结合代码来进一步分析一下上面的步骤:

function cat(name) {
    var a = '年年';
    var b = function () {};
    this.name = name;
    function c() {
        console.log(this.name);
    }
    c();
}
cat('有鱼');

这段代码在调用函数 cat('有鱼')时,执行上下文是处于 创建阶段的,代码解析为:

cat执行上下文对象 = {
    scopeChain: { ... },// 1.创建作用域链,开辟栈内存
    variableObject: { 2.创建变量对象
        arguments: {  // 2.1 解析参数
            0: '有鱼',
            length: 1
        },
        name: '有鱼',  // 2.1 解析参数,创建形参名称,并进行参数赋值
        c: function c()  // 2.2 找到函数声明c,并将c作为属性,function c作为值
        a: undefined,  // 2.3 找到变量声明a,初始化为undefined,该阶段只看声明部分,不进行赋值
        b: undefined   // 2.3 找到变量声明b,初始化为undefined,该阶段只看声明部分,不进行赋值
    },
    this: {  3.创建this对象
        this:cat('有鱼') // 3.1 指向此次调用的对象
        name:undefined // 3.2 对象属性name的初始化为undefined
    };
    c() //又进入函数c执行上下文,跟cat函数一样,暂不展开 
}

通过代码解析我们可以得出以下结论:
①三个步骤顺序不能乱
②VO步骤内,先执行函数声明,再执行变量声明
③只有参数可以在此阶段进行赋值,变量、函数都只能声明


执行堆栈.png

(二)执行阶段
该阶段JS解释器执行上下文中的函数代码,逐行运行JS代码,并给变量赋值;
还是结合代码来分析:

cat执行上下文对象 = {
    scopeChain: { ... },
    variableObject: { 
        arguments: { 
            0: '有鱼',
            length: 1
        },
        name: '有鱼', 
        c: function c(),
        a: '年年',  // 变量a进行赋值
        b: function b   // 变量b进行赋值
    },
    this: {  3.创建this对象
        this:cat('有鱼') 
        name:'有鱼' // 对象属性name进行赋值
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,589评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,615评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,933评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,976评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,999评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,775评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,474评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,359评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,854评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,007评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,146评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,826评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,484评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,029评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,153评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,420评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,107评论 2 356

推荐阅读更多精彩内容