二、js执行过程

上文的结尾我们提到了js的执行过程,那么下面我们就来谈一下js的执行过程

一、代码被解析——初始化全局对象

VO(Variable Object):全局变量对象

AO(Active Object):私有变量对象

JavaScript源代码在通过解析(Parse)转为AST之前,v8引擎会在堆内存中创建一个全局对象GlobalObject(GO)

  • 这个对象所有的作用域都可以访问
  • 包括Data,String,Number,console.log等都会放在GO中
  • 其中还有一个属性:window指向自己(GO)
  • 全局的变量和函数都会放在GO中,不同的是:在编译阶段,变量的值是undefined,而函数的值是 函数体在内存中的地址

二、运行代码

1.ECS

v8为了执行代码,v8引擎内部会有一个执行上下文栈(Execution Context Stack,ECS),也叫做函数调用栈,它用于执行代码中的调用栈。

2.GEC

ECS要执行什么呢?执行的是全局的代码块

  • 为了执行全局的代码块,会创建一个全局执行上下文Global Execution Context(GEC)
  • 在GEC中,VO指的就是GO
  • GEC会被放在ECS中执行

3.GEC被放入ECS中执行,其中有两个过程:

  • 在代码执行前,在parser转成AST的过程中,会将全局定义的变量,函数等加入到GO中(在上面提到过),如果是变量,那么仅仅是对变量做声明,并不会对它们进行赋值,这个过程也叫做变量的作用域提升;如果是函数,那么除了存放函数名,还会存放函数的值,也就是函数体在内存中的位置
  • 在代码执行过程中,代码顺序执行,比如对变量赋值,或者执行其他函数

4.FEC

ECS要执行什么呢?执行的是全局的代码块

  • 为了执行全局的代码块,会创建一个全局执行上下文(GEC)

  • 如果在执行过程中遇到函数,就会根据函数体创建一个函数执行上下文(Functional Execution Context,FEC),并且压入ECS栈中

  • 在FEC中,VO指的是AO(Active Object):用于存放函数体内部的变量,函数。同样,在编译阶段,变量的值是undefined,函数的值是 函数体在内存中的地址

  • FEC中包含三部分内容:

    1)在解析函数称为AST树时,会创建AO,AO中包含形参、arguments、函数定义和指向函数对象、定义的变量

    2)作用域链(scope chain):由VO(在函数中就是AO)和父级VO(父级如果是全局对象,那么就是GO,如果是私有(函数)对象,那么就是AO)组成,查找时由内向外一层层查找

    3)this绑定的值,这个后面会详细叙述

三、案例1

var name = 'captain'
console.log(name)
console.log(num1)
var num1 = 20
var num2 = 30
var sum = num1 + num2
console.log(sum)

在上述代码中,

1.创建全局对象GO

  • 在编译阶段,除了包括内置的变量、类、方法等之外,还会将上述代码中的name、num1,num2,sum等名称加入到GO中,相当于在全局做了变量声明,只知道变量存在,但不知道具体的值

2.然后执行代码

把GEC放入到ECS中,GEC中的VO就是GO,然后顺序执行代码,执行代码过程中,遇到变量、函数,会去GEC中的VO中找,也就是GO中找

  • 第一行,对变量name进行赋值
  • 第二行,打印name的值为captain
  • 第三行,打印num1的值为undefined,这是因为目前只做了变量的声明,但是还没有赋值,所以不会报错说没有这个变量,也不会说变量的值,只会打印undefined
  • 第四行,对num1进行赋值
  • 第五行,对num2进行赋值
  • 第六行,对sum进行赋值
  • 第七行,打印sum的值为50

四、案例2

var name = 'captain'
foo()
function foo() {
    var num = 20
    console.log(name)
}
foo()

在上述代码中

1.创建全局对象GO和私有对象AO

  • 在编译阶段,除了包括内置的变量、类、方法等之外,还会将name存入GO中,name的值为undefined,还有foo也会放入GO中,foo的值为foo函数体的内存地址
  • 对函数foo函数体进行预编译,将num存放在AO中,但是值为undefined

2.然后执行代码

把GEC放入到ECS中,然后顺序执行代码,执行代码过程中,遇到变量、函数,会去GEC的VO中找,也就是GO中找

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

推荐阅读更多精彩内容