Skip to content

JS运行原理 #2

@coconilu

Description

@coconilu

简述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引擎等等。

它们都有以下两个主要特性:

  1. 单线程
  2. 同步执行

这两个特性省去了多线程的锁机制,降低了编程的门槛。

2. 解释执行JS文件

伪逻辑如下:

2.1 创建全局执行上下文

主要任务:
创建执行上下文栈
创建变量对象,包括初始化的全局对象,函数声明,变量声明
并把this指向全局对象(浏览器环境下是window)

2.2 从上至下解释执行语句

2.2.1 如果遇到的是函数执行语句

创建新的执行上下文,并放入执行上下文栈的栈顶
新的执行上下文主要有如下三个对象

  1. 作用域链,根据执行上下文栈求出作用域链
  2. 创建变量对象,包括arguments,函数声明,变量声明
  3. 定义this的指向

2.2.2 如果遇到的是异步语句

比如setTimeout,setInterval,Promise之类,将会交给异步处理模块,待到时机成熟的时候,它们会把回调放到任务队列中。

2.2.3 如果遇到的是创建新对象的语句

则把该对象放到堆里

2.3 主线程执行完之后进入事件循环阶段

事件循环阶段的伪逻辑如下:

  1. 运行micro-task队列的任务直到为空
  2. 然后再运行macro-task队列里截止目前存在的任务
  3. 回到1

可以参考我的另一篇博客《异步编程与事件循环》下对任务队列的讲解。

2.4 循环直到程序结束

最后总结一下

js

从上图可以看出,核心在执行上下文栈(JS线程),它关联着存储对象的堆,调用异步模块来处理异步任务,并不断从任务队列中索取回调来执行。

图中的异步处理模块几乎都是独立于JS线程的浏览器其他线程,比如定时器,就是浏览器的另一条线程,注册定时任务的时候,会在固定的时间之后把回调放入任务队列中。

接下来,拓展你的思维

浏览器进程和网页渲染过程
执行上下文
类相关
异步编程与事件循环

参考链接

https://www.kancloud.cn/digest/liao-js/149467
冴羽的博客
异步编程

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions