-
Notifications
You must be signed in to change notification settings - Fork 20
Description
简述JS运行原理的概念
这是一个涉及到编译原理的问题。简单来说,一般一个JS文件被执行的时候,是会经过扫描代码,并进行语法分析、语义分析等等步骤的,然后生成一些诸如语法树、符号表之类的数据结构,最后才是从上至下执行代码。
了解运行原理有什么用?
了解运行原理,才能更好预测到代码的效果,才能从容面对各种奇怪bug,以及一些提问运行结果的面试题。
如下:
console.log(a) // [Function: a]
var a = 1
function a () {}
console.log(a) // 1这里涉及到了JS引擎的提升(hoisting)
JS运行原理的具体过程
1. 先简单介绍 JS引擎
JS引擎是根据ECMAScript规定的文档去实现的,这些文档定义了一些规则,然后呢,各个浏览器厂商就根据这些规则去实现自己的JS引擎,有点像Java的接口编程,所以目前的主流JS引擎有:Firefox浏览器为Gecko引擎,Safari为WebKit引擎,Chrome为Blink引擎等等。
它们都有以下两个主要特性:
- 单线程
- 同步执行
这两个特性省去了多线程的锁机制,降低了编程的门槛。
2. 解释执行JS文件
伪逻辑如下:
2.1 创建全局执行上下文
主要任务:
创建执行上下文栈
创建变量对象,包括初始化的全局对象,函数声明,变量声明
并把this指向全局对象(浏览器环境下是window)
2.2 从上至下解释执行语句
2.2.1 如果遇到的是函数执行语句
创建新的执行上下文,并放入执行上下文栈的栈顶
新的执行上下文主要有如下三个对象
- 作用域链,根据执行上下文栈求出作用域链
- 创建变量对象,包括arguments,函数声明,变量声明
- 定义this的指向
2.2.2 如果遇到的是异步语句
比如setTimeout,setInterval,Promise之类,将会交给异步处理模块,待到时机成熟的时候,它们会把回调放到任务队列中。
2.2.3 如果遇到的是创建新对象的语句
则把该对象放到堆里
2.3 主线程执行完之后进入事件循环阶段
事件循环阶段的伪逻辑如下:
- 运行micro-task队列的任务直到为空
- 然后再运行macro-task队列里截止目前存在的任务
- 回到1
可以参考我的另一篇博客《异步编程与事件循环》下对任务队列的讲解。
2.4 循环直到程序结束
最后总结一下
从上图可以看出,核心在执行上下文栈(JS线程),它关联着存储对象的堆,调用异步模块来处理异步任务,并不断从任务队列中索取回调来执行。
图中的异步处理模块几乎都是独立于JS线程的浏览器其他线程,比如定时器,就是浏览器的另一条线程,注册定时任务的时候,会在固定的时间之后把回调放入任务队列中。
接下来,拓展你的思维
浏览器进程和网页渲染过程
执行上下文
类相关
异步编程与事件循环
