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 | function multiply(x, y) { |
回调过程正如你想象的那样
每一次进入回调栈我们都称之为一次栈帧。
异常的情况也必须进入这个状态
Blowing the stack
当事件队列达到栈的max值时,你可以想象到会发生什么情况
1 | function foo() { |
当引擎执行这段code时,会发生无限的回调,这个过程无休止
单线程虽然handle的情况不算多,但是也有绝佳的好处,比如说不必处理多线程环境中出现的复杂场景 - 例如,死锁。
那我们自然也会需要多种任务共同处理的状况,为此引入并发的概念。
Concurrency & the Event Loop
假如调用堆栈有一些函数必须处理复杂的操作,耗费掉大量的时间,会发生什么?比如想在浏览器中使用JavaScript进行一些复杂的图像转换。浏览器很可能会卡住,stuck掉之后的渲染的流程,造成糟糕的视觉体验。
那么,如何在不阻止UI并使浏览器无响应的情况下执行繁重的代码呢?
答案是异步回调。
这一部分将在第二部分给出。
Translate By cococola & google.
若你觉得我的文章对你有帮助,欢迎点击上方按钮对我打赏
扫描二维码,分享此文章