图解 Google V8
李兵
前盛大创新院高级研究员
立即订阅
3745 人已学习
课程目录
已完结 25 讲
0/4登录后,你可以任选4讲全文学习。
宏观视角 (2讲)
开篇词 | 如何学习谷歌高性能 JavaScript 引擎V8?
免费
01 | V8是如何执行一段JavaScript代码的?
JavaScript设计思想篇 (7讲)
02 | 函数即对象:一篇文章彻底搞懂JavaScript的函数特点
03 | 快属性和慢属性:V8是怎样提升对象属性访问速度的?
04 | 函数表达式:涉及大量概念,函数表达式到底该怎么学?
05|原型链:V8是如何实现对象继承的?
06|作用域链:V8是如何查找变量的?
07|类型转换:V8是怎么实现1+“2”的?
08|答疑:如何构建和使用V8的调试工具d8?
V8编译流水线 (8讲)
09 | 运行时环境:运行JavaScript代码的基石
10 | 机器代码:二进制机器码究竟是如何被CPU执行的?
11 | 堆和栈:函数调用是如何影响到内存布局的?
12 | 延迟解析:V8是如何实现闭包的?
13 | 字节码(一):V8为什么又重新引入字节码?
14|字节码(二):解释器是如何解释执行字节码的?
15 | 隐藏类:如何在内存中快速查找对象属性?
16 | 答疑: V8是怎么通过内联缓存来提升函数执行效率的?
事件循环和垃圾回收 (6讲)
17 | 消息队列:V8是怎么实现回调函数的?
18 | 异步编程(一):V8是如何实现微任务的?
19|异步编程(二):V8是如何实现async/await的?
20 | 垃圾回收(一):V8的两个垃圾回收器是如何工作的?
21 | 垃圾回收(二):V8是如何优化垃圾回收器执行效率的?
22|答疑:几种常见内存问题的解决策略
结束语 (2讲)
结束语 | 我的前端学习踩坑史
结课测试 | 这些V8的知识你都掌握了吗?
图解 Google V8
15
15
1.0x
00:00/00:00
登录|注册

09 | 运行时环境:运行JavaScript代码的基石

李兵 2020-04-04
你好,我是李兵。
通过前面几节课的学习,我们理解了 JavaScript 是一门基于对象的语言,它能实现非常多的特性,诸如函数是一等公民、闭包、函数式编程、原型继承等,搞懂了这些特性,我们就可以来打开 V8 这个黑盒,深入了解它的编译流水线了。
我们知道,当你想执行一段 JavaScript 代码时,只需要将代码丢给 V8 虚拟机,V8 便会执行并返回给你结果。
其实在执行 JavaScript 代码之前,V8 就已经准备好了代码的运行时环境,这个环境包括了堆空间和栈空间、全局执行上下文、全局作用域、内置的内建函数、宿主环境提供的扩展函数和对象,还有消息循环系统。准备好运行时环境之后,V8 才可以执行 JavaScript 代码,这包括解析源码、生成字节码、解释执行或者编译执行这一系列操作。
对运行时环境有足够的了解,能够帮助我们更好地理解 V8 的执行流程。比如事件循环系统可以让你清楚各种回调函数是怎么被执行的,栈空间可以让你了解函数是怎么被调用的,堆空间和栈空间让你了解为什么要有传值和传引用,等等。
运行时环境涉及到的知识都是非常基础,但又非常容易被忽视的。今天这节课,我们就来分析下这些基础的运行时环境。

什么是宿主环境?

要聊运行 V8 的运行时环境,我们不得不聊 V8 的宿主环境,什么是 V8 的宿主环境呢?
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《图解 Google V8》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(21)

  • 王楚然
    思考题:
    1. 作用域是静态的,函数定义的时候就已经确定了。
    2. 执行上下文是动态的,调用函数时候创建,结束后还会释放。
    不知这样理解对不对
    2020-04-04
    1
    15
  • 侯不住
    这个事件循环一直有个点不太明白,事件循环是跑在主线程的,需要不断轮询,它在没有任务的时候是如何保证不卡死的,就像我们随便写一段死循环,cpu都100%了,它是如何做的?

    作者回复: 实际上是事件驱动的!

    也就是说,如果没有任务,那么该线程将被挂起,一旦有新的任务到达了消息队列,那么系统会将这个挂起的线程激活,激活之后线程继续向下执行!


    我在例子中使用的是while(1)这是为了讲解方便,实际项目中不可能这样用的!

    比如node使用的是libuv就封装好了这种机制,Chrome浏览器中相对复杂点,但是本质一样!

    2020-04-10
    8
  • 蒋悦
    作用域是逻辑概念,只要函数确定,作用域就确定了。执行上下文其实就是“栈帧”。作用域和子作用域有从属关系,是静态的。执行上下文是函数的调用关系,是动态的。
    2020-04-04
    6
  • 爱吃锅巴的沐泡
    老师您好,对于ES5标准文档中规定,
             执行环境包括:词法环境、变量环境、this绑定。
             其中执行环境的词法环境和变量环境组件始终为词法环境对象。当创建一个执行环境时,其词法环境组件和变量环境组件最初是同一个值。在该执行环境相关联的代码的执行过程中,变量环境组件永远不变,而词法环境组件有可能改变。

    问题1:变量环境组件永远不变,而词法环境组件有可能改变。 
              这里您给出的解释是说词法环境里会有块级作用域的进入和退出,但这是ES5的规范呀,还没有作用域的概念呀,这里不解?
              变量环境组件为什么永久不变?

    问题2:创建执行环境时,变量环境和词法环境最初是同一个值,想知道这个值具体是指什么值?

    问题3:我理解的ES5中 变量环境中存储的是提升的变量和函数声明(都是类似var xx=undefined; function funname(){}),所以变量环境是不变的,在执行过程中变量的变化是在词法环境中体现的,词法环境管理着静态作用域的。 到了ES6,有了let和const,是不是就把原来词法环境中变化的变量转移到了变量环境中,把let和const的变化放到了现在的词法环境中。

    希望老师能举个例子或者画个图,详细分析一下在ES5中变量环境和词法环境中变量的变化?
    ES5和ES6的执行环境的区别是啥?

    问题有点多,但是网上写的和规范内容都不一样,感觉不靠谱,请老师解答!
    2020-04-04
    5
    5
  • 一步
    作用域是依附执行上下文的,如果执行上下文销毁,那么对应的作用域也会销毁(这里闭包形成的作用域是特例)
    2020-04-04
    4
  • OnE
    V8运行时环境里的栈空间,在操作系统层面,到底是属于进程堆,还是进程栈呢?如果是后者,背后的实现机理是什么样的呢?
    2020-04-04
    3
  • 桃翁
    老师,有个疑惑希望您能解答,我看您的图:宿主环境和V8的关系 里面堆栈空间是属于 宿主环境的,但是我看很多文章写的都是 堆栈是属于 v8 引擎提供的,不知道哪个是正确的。
    我其实比较偏向与是 v8提供的,因为他要进行垃圾回收,如果 v8 来提供可能比较好管理一点。

    作者回复: 因为是一个进程内部的,所以宿主和v8共同一套内存空间,通常在启动V8的过程中,宿主会创建好堆和栈的空间,在V8中叫isolate,然后V8利用创建好的堆和栈!

    所以不用纠结谁创建的,因为他们使用的是一套内存

    2020-04-07
    1
    2
  • 大力
    老师,有个地方我有个疑问:

    文中说,“全局执行上下文在 V8 的生存周期内是不会被销毁的,它会一直保存在堆中”。

    而文中又另外说到,“在函数调用过程中,涉及到上下文相关的内容都会存放在栈上”。

    那究竟全局上下文是放在堆上还是栈上呢?

    我的理解是应该都放在栈上,因为总不会函数执行上下文放在栈上,而全局执行上下文放在堆上吧?

    还望指正。
    2020-04-19
    3
    1
  • tt
    我认为执行上下文是作用域的实现。
    2020-04-05
    1
  • bright
    执行上下文是用来维护执行当前代码所需要的变量声明、this 指向等。作用域是规定了如何查找变量,也就是确定当前执行代码对变量的访问权限。js采用的是词法作用域,函数的作用域在函数定义的时候就决定了。可以把作用域看作执行上下文中代码对变量的访问权限。
    2020-04-04
    1
  • 非洲大地我最凶
    而栈空间是连续的,所以堆空间中的查找速度非常快, 此处应该是栈的查找速度快吧
    2020-04-04
    2
    1
  • sh
    总结的很好啊
    2020-06-06
  • zlxag
    李兵 老师你为什么在文章说。js是基于对象的语言,而不是面向对象语言。”基于“ 和 ‘面向’的的区别是?
    面向对象的语言 有唯一性,有状态,且有状态的变化(行为)为对象,这些js都满足。老师的 ”基于“,不知道出于什么考虑

    作者回复: 基于对象你可以理解为这门语言的零件都是由对象组成的,而面向对象是通常用来实现OOP编程,支持封装,继承,多态

    2020-04-26
  • Geek_177f82
    我有个疑问,1,队列中任务的极限是多少?2,如果列队中任务足够多的时候,消息队列这个时候是怎么处理的?还可以添加到队列,还是?
    2020-04-09
  • 桃翁
    老师,执行上下文里的词法环境和变量环境有什么区别呢?后面的课程会讲解吗

    作者回复: 词法环境和变量环境在浏览器专栏中花了好几个篇幅来介绍,在V8专栏中没有打算展开来讲了

    2020-04-08
  • 黄万万很有才
    不懂就问:匿名函数的上下文为什么全局执行上下文呢?看了很多,结论都是:就是这样定义的,就是把匿名函数的上下文定义为全局,所以非严格模式下匿名函数的this指向window。
    2020-04-07
  • 伏枫
    我有个问题:事件循环和js主执行栈是在同一个线程运行么?如果是一个线程,那么事件循环不会阻碍主执行栈么?

    作者回复: 会啊,如果当前一个任务在执行,那么主线程上的其他任务都要等待

    2020-04-06
  • 桃翁
    我一直觉得作用域是在执行上下文内的,变量环境感觉就是作用域的样子。但是又考虑到作用域在编译时就确定了,而执行上下文是运行时才创建的,所以是在运行的时候把作用域映射到变量环境的吗
    2020-04-06
    1
  • 彭越
    词法和文法决定了变量作用域,可以说是静态的,在运行前就决定了。执行上下文则是动态的,运行期创建的,根据JavaScript代码创建执行上下文,包含了VO、Scope chain、thisValue这些根据js代码生成的运行期信息。到了function的执行上下文,则会生成AO,包含了function内部变量、arguments等信息。
    2020-04-05
  • Beliforever
    我想问一下在全局环境中{}里声明的let const 变量存在全局的词法环境中吗
    2020-04-04
    1
收起评论
21
返回
顶部