Bermu

JavaScript如何工作,一份关于引擎,运行时,堆栈的清单

2018-11-13

JavaScript日渐流行,团队借由它的生态支持在多个级别进行了储备:前端,后端,混合应用,嵌入式设备等等。


本文是对JavaScript的运行机制深度探讨的系列第一篇,旨在说明构建块是如何集成发挥作用的,理解了这些,你将会更好地写code或者app。


如果项目有更多的依赖相关处于JS这一方,这意味着开发者必须物尽其用,且深入理解其精髓,才可以写出巧夺天工的软件。


OverView

几乎人人都听说过V8的大名,并且知道JS是单线程的,拥有一个回调队列。


在文章中,我们会详细阐述JS真正的运行方式,了解了API的正确使用方式,会帮助你构建出无阻塞的程序。

The JavaScript Engine

V8引擎被用于Chrome与Node.js当中,是非常受欢迎的引擎,一个简单的图例类似这样👇🏻

引擎包括了两个主要部分


  • Memory Heap 这是内存分配的地方
  • Call Stack 代码执行时堆栈帧的位置

The Runtime

这样的API你一定不陌生,比如说setTimeout,它的运行图示为👇🏻

还有一些叫做Web API的东西,它们是由浏览器提供的,比如DOM,AJAX等等。形成了如此受欢迎的事件循环和回调队列。

The Call Stack

调用栈是一种数据结构,它基本上记录了程序中的位置。当我们进入函数体内部时,我们将它放在堆栈的顶部。如果从函数返回,我们会在堆栈的顶部弹出。这是显而易见的。


让我们看一个例子


1
2
3
4
5
6
7
8
function multiply(x, y) {
return x * y;
}
function printSquare(x) {
var s = multiply(x, x);
console.log(s);
}
printSquare(5);

回调过程正如你想象的那样


每一次进入回调栈我们都称之为一次栈帧


异常的情况也必须进入这个状态


Blowing the stack

当事件队列达到栈的max值时,你可以想象到会发生什么情况


1
2
3
4
function foo() {
foo();
}
foo();


当引擎执行这段code时,会发生无限的回调,这个过程无休止

单线程虽然handle的情况不算多,但是也有绝佳的好处,比如说不必处理多线程环境中出现的复杂场景 - 例如,死锁。


那我们自然也会需要多种任务共同处理的状况,为此引入并发的概念。

Concurrency & the Event Loop

假如调用堆栈有一些函数必须处理复杂的操作,耗费掉大量的时间,会发生什么?比如想在浏览器中使用JavaScript进行一些复杂的图像转换。浏览器很可能会卡住,stuck掉之后的渲染的流程,造成糟糕的视觉体验。


那么,如何在不阻止UI并使浏览器无响应的情况下执行繁重的代码呢?


答案是异步回调。


这一部分将在第二部分给出。



Translate By cococola & google.

原文出处

使用支付宝打赏
使用微信打赏

若你觉得我的文章对你有帮助,欢迎点击上方按钮对我打赏

扫描二维码,分享此文章