来源 | hashnode.com/@ganeshjaiwal
译者 | 鬼哥
您是否知道简单的JavaScript语句需要大量工作才能完成?
嗯...
所以浏览器无法直接理解javascript。
那我们该如何要求浏览器做些什么呢?
让我们从浏览器理解的语言开始。
浏览器仅理解0和1s语言,即二进制/位格式的语句。
我们无法轻松地将整个JavaScript转换为位。那么,我们现在该怎么办???
JavaScript引擎:- “嘿,不用担心,我可以为您提供JavaScript文件。”
那么什么是JavaScript引擎?
当将JavaScript文件加载到浏览器中时,JavaScript Engine会从上到下逐行执行该文件(异步代码将是一个例外,我们将在本系列后面的内容中看到异步代码)。
JavaScript引擎将逐行解析代码并将该代码转换为机器代码(二进制/位格式)。
现在,浏览器可以理解该机器代码并相应地运行。
这是一些JS引擎示例。
那么这个javascript引擎里面是什么?
这是JavaScript引擎的非常基本的视图。
内存堆
JavaScript引擎有时无法在编译时分配内存,因此在运行时分配的变量将进入内存堆(内存的非结构化区域)。即使我们退出在堆中分配内存的函数,我们在堆部分中分配的数据/对象仍然存在。
在这里,我们面临一个主要的内存泄漏问题。
那么什么是内存泄漏?
内存堆的空间有限。如果我们继续使用堆空间而不关心释放未使用的内存。当堆中没有更多可用内存时,这将导致内存泄漏问题。
为了解决此问题,javascript引擎引入了垃圾收集器。
什么是垃圾收集器?垃圾回收是内存管理的一种形式。就像一个收集器,它试图释放不再使用的对象所占用的内存。换句话说,当一个变量失去所有引用时,垃圾回收将该内存标记为“无法访问”并释放它。
执行上下文栈
堆栈是遵循后进先出(LIFO)原理的数据结构(进入堆栈的最后一项将是要从堆栈中删除的第一项)。
ECS存储所有功能的执行上下文。执行上下文定义为存储局部变量,函数和对象的对象。
简而言之,每个功能都被推到袋子的顶部。
JavaScript引擎执行此堆栈顶部的功能。
由于JavaScript引擎只有一个ECS,因此一次只能执行一件事情,这是ECS的顶部。这就是使JavaScript单线程的原因。
您一定听说过堆栈溢出。
这意味着什么?-ECS的空间也有限。因此,如果我们继续在堆栈顶部添加功能。在某个时候,将没有更多的空间来添加更多的堆栈框架。在这一点上,我们得到一个堆栈溢出错误。
考虑以下示例。
- function heyJS() {
- console.log("Hello you are awesome!!!!");
- heyJS();
- }
- heyJS();
好吧,这进入了无限递归,并且我们有一个堆栈溢出错误。
因此,正如我所提到的,JavaScript是一种简单的线程语言,这意味着它只有一个调用堆栈广告,因此一次只能执行一个语句。
等等,我们也听说过用JavaScript进行异步编程。那么,一次只允许一项任务时,该如何工作?
这是Web API的和回调队列。
Web API
Web API不是JS引擎的一部分,而是Web浏览器提供的JavaScript运行时环境的一部分。JavaScript只是为我们提供了一种访问这些API的机制。由于Web API是特定于浏览器的,因此它们可能因浏览器而异。在某些情况下,某些Web API可能存在于一个浏览器中,而没有出现在另一浏览器中。
例子:-
- document.getElementById();
- document.addEventListerner();
- setTimeOut();
- setInterval();
- 例:-
- console.log(“First!”);
- setTimeout(() => {
- console.log(“Second!”);
- }, 1000 );
- console.log(“Third!”);
- /*
- OutPut:-
- First
- Third
- Second
- */
很奇怪吧?
“第二”位于setTimeout内部,因此将在1秒后执行。
幕后到底发生了什么?
1秒钟后,WebAPI将得到通知,嘿,您有需要立即执行的代码。WebAPI “哦,这是console.log(),我需要执行它,但是我不能直接执行它。让我们将其发送到Callback Queue” “嘿,这里是回调的Queue,请将其添加到列表中并执行。”
回调队列
回调队列或消息队列是遵循先进先出原则的队列数据结构(首先插入队列的项目将首先从队列中删除)。它存储所有从事件表移至事件队列的消息。每个消息都有一个关联的功能。回调队列维护消息或方法在队列中添加的顺序。
事件循环
事件循环不断检查执行上下文堆栈是否为空以及事件队列中是否有任何消息。仅当执行上下文堆栈为空时,才会将方法从回调队列移至ECS。
回调队列
“嘿,事件循环请检查ECS是否为空。我有一些需要推送到ECS中的回调”。
事件循环
“队列,请给我回调,ECS现在为空,我将它们压入堆栈以执行它们。”
最后,最后,我们将获得输出。
- // First
- // Third
- // Second
这只是JavaScript引擎工作原理的概述。
JavaScript引擎比我们今天在这里讨论的方式复杂得多。
我将在以后的一些文章中尝试更深入地了解JavaScript引擎。
在本系列的下一篇文章中,我将解释Javascript类型,值和变量。
本文转载自微信公众号「前端人」,可以通过以下二维码关注。转载本文请联系前端人公众号。