首页 web前端 js教程 JavaScript 的底层是如何工作的?

JavaScript 的底层是如何工作的?

Jan 01, 2025 am 08:11 AM

这篇文章的真正目的是以一种简单的方式介绍 JavaScript 在底层如何工作,这样即使是新程序员也能够掌握这个概念并可视化编写 JavaScript 时会发生什么。
首先,我想关注至少 3 个问题,这将有助于克服困难并内化背后的逻辑?
这些问题也是 Web 开发人员面试期间可能会被问到的问题,其中 JavaScript 意味着:

1。 JavaScript 是如何工作的?
2.解释一下同步和异步的区别?
3.或者解释一下这句话:JavaScript是单线程语言,可以是非阻塞的?

确实,编写程序并不需要了解 JavaScript 内部工作原理,但学习 JavaScript 是必要且至关重要的,以便了解背后发生的事情并感受您正在编写的内容,因此对于许多拥有多年经验的开发人员来说运营商不想知道这一点。

让我们先知道什么是程序?程序只是一组指令,告诉计算机要做什么以及如何执行任务。程序必须分配内存,否则,我们将无法在计算机上拥有变量,甚至无法保存文件。程序还应该解析(读取)并执行专用任务,并且所有操作都发生在内存中。

现在,JavaScript 拥有每个浏览器都实现的名为 JavaScript 引擎 的引擎。例如,在 Chrome 中,它称为 V8,在 Mozilla Firefox 中:Spider Monkey,Safari 浏览器:JavaScript Core Webkit。

下图为 google chrome 的 V8 引擎
How JavaScript works underneath the hood?

JavaScript 引擎内部发生了什么?

JavaScript 引擎(例如 Chrome 中的 V8)读取我们编写的 JavaScript 代码,并将其转换为浏览器的机器可执行指令。上图显示了 JavaScript 引擎的各个部分,它由两部分组成,即内存堆**和**调用堆栈

还需要注意的是,内存分配发生在内存堆中,而解析(读取)和执行发生在调用堆栈中。除此之外,内存堆告诉你你在程序中的位置。

让我们用 JS (JavaScript) 代码看看内存堆中的内存分配

const a = 4;  // now we allocated a memory. JS engine is going to remember
// that a has a value of 4. 

const Obj = {a, b, c };  // In memory, variable 'Obj' holds the object {a, b,c}

// The same as on array. the engine will remember values of the array
const Array = [1,2,3,4,5]
登录后复制
登录后复制
登录后复制
登录后复制

那么,上述代码在全局声明后会出现什么问题呢?

有一种叫做内存泄漏的东西。如上所述,变量声明发生在内存堆中,并且它的分配大小是有限的。当您继续声明非常大的数组而不是数字甚至未使用的全局变量时,这会填满内存并导致内存泄漏。你会听说全局变量很糟糕,因为当我们忘记清理时,我们会填满这个内存堆,最终浏览器将无法工作。

调用堆栈怎么样?

如果我们还记得的话,读取和执行脚本的是调用堆栈。我们用代码来说明一下吧。

const a = 4;  // now we allocated a memory. JS engine is going to remember
// that a has a value of 4. 

const Obj = {a, b, c };  // In memory, variable 'Obj' holds the object {a, b,c}

// The same as on array. the engine will remember values of the array
const Array = [1,2,3,4,5]
登录后复制
登录后复制
登录后复制
登录后复制

使用上面的代码,调用sack读取第一行console.log(“x”);并被放入调用堆栈中,JavaScript引擎识别出console.log已被添加,然后将其弹出到调用堆栈中,运行它并输出x。之后,它会删除第一个 console.log,因为它已完成运行,并将其放入第二个 console.log(“y”),将其添加到调用堆栈中,执行 y 并删除第二个 console.log。最后使用相同的过程获取console.log(“z”)。

这是最简单的演示,如果再复杂一点怎么办?举个典型的例子:


// Example Call Stak

console.log("x");
console.log("y");
console.log("z");

// Result in browser

// x
// y
// z
登录后复制
登录后复制
登录后复制
现在,根据调用堆栈,上面的代码发生了什么?让我们看看它将如何运行上面的代码块:

//调用堆栈

函数

example1() 将首先运行,然后函数 example2() 出现在调用堆栈的顶部并运行,在检查是否存在后打印出数字 7 作为输出其他要运行的代码。之后,它将开始按从 console.log(‘7’)、example2()、example1() 开始的顺序从调用堆栈中删除,并且调用堆栈现在为空。

>我们还记得这句话吗? JavaScript 是一种非阻塞的单线程语言。

单线程意味着它只有一个调用堆栈。它一次只能执行一件事,重要的是要强调调用堆栈是先进后出的,就像堆栈

其他语言可以有许多调用堆栈,即所谓的

多线程,拥有多个调用堆栈可能更有利,这样我们就不必一直等待任务。

>但是,为什么 JavaScript 被设计为单线程呢?

要回答这个问题,通常在单线程上运行代码非常容易,因为多线程环境中不会出现复杂的场景。你实际上有一件事情需要关心。在多线程中,可能会出现死锁之类的问题。有了这个理论,我们就很容易知道同步编程意味着什么

同步编程简单来说就是:执行第一行代码,执行第二行代码,执行第三行代码,等等......

更明确地说,这意味着 console.log(“y”) 无法运行,直到 console.log(“x”) 完成并且 console.log (“z”) 直到前两个都完成后才开始,因为它是一个 调用堆栈

程序员很可能会使用 stackoverflow.com 网站。这个名字是什么意思?出色地。让我们看看:

How JavaScript works underneath the hood?
堆栈溢出是如何发生的

上图显示了内存泄漏是如何发生的以及 JavaScript 引擎的内存堆如何溢出。这里,调用堆栈接收许多大于其大小的输入并溢出。

可以借助代码来演示堆栈溢出:

const a = 4;  // now we allocated a memory. JS engine is going to remember
// that a has a value of 4. 

const Obj = {a, b, c };  // In memory, variable 'Obj' holds the object {a, b,c}

// The same as on array. the engine will remember values of the array
const Array = [1,2,3,4,5]
登录后复制
登录后复制
登录后复制
登录后复制

请注意,JavaScript 是单线程的,一次只执行一个语句。 现在有一个问题:如果下面代码块中的console.log(“y”)有一个需要更长时间才能完成的大任务怎么办?例如循环遍历具有数千或数百万项的数组?那里会发生什么?

// Example Call Stak

console.log("x");
console.log("y");
console.log("z");

// Result in browser

// x
// y
// z
登录后复制
登录后复制
登录后复制

第一行将执行,并假设第二行有大量工作要执行,因此第三行将等待很长时间才能执行。在上面的示例中,这没有多大意义,但让我们想象一个执行繁重操作的大型网站,用户将无法执行任何操作。网站将冻结,直到任务完成并且用户在那里等待。对于表演来说这是一次糟糕的体验。

嗯,对于同步任务,如果我们有一个函数需要花费很多时间,那么它就会阻塞队列。所以,听起来我们需要一些非阻塞的东西。请记住我上面提到的那句话:JavaScript 是一种可以非阻塞的单线程语言。

理想情况下,在 JavaScript 中我们不会等待需要时间的事情。那么,我们该如何解决这个问题呢?

作为救援,有异步编程。那么,这是什么?

将异步视为一种行为。同步执行很棒,因为它是可预测的。在同步中,我们知道首先发生什么,接下来发生什么等等,但它可能会变慢。

当我们必须执行图像处理或通过网络发出请求(例如 API 调用)等操作时,我们使用的不仅仅是异步同步任务。

让我们看看如何用代码进行异步编程:

const a = 4;  // now we allocated a memory. JS engine is going to remember
// that a has a value of 4. 

const Obj = {a, b, c };  // In memory, variable 'Obj' holds the object {a, b,c}

// The same as on array. the engine will remember values of the array
const Array = [1,2,3,4,5]
登录后复制
登录后复制
登录后复制
登录后复制

现在,根据上面的代码,我们似乎跳过了第二行并执行第三行,并等待 3 秒输出结果。这是异步发生的。

为了理解这一点以及发生了什么,让我们使用下图。

How JavaScript works underneath the hood?
JavaScript 运行时环境

为了运行 JavaScript,我们需要的不仅仅是内存堆和调用堆栈。我们需要所谓的 JavaScript Run-Time,它是浏览器的一部分。它包含在浏览器中。在引擎之上,有一些称为Web API,回调队列事件循环,如图所示。

现在我们来讨论一下使用 setTimeout 函数的代码。

// Example Call Stak

console.log("x");
console.log("y");
console.log("z");

// Result in browser

// x
// y
// z
登录后复制
登录后复制
登录后复制

setTimeout 函数 是 Web API 的一部分,而不是 JavaScript 的一部分,相反,它是浏览器提供给我们用来进行异步编程的函数。因此,让我们提供更多详细信息以进行澄清。

调用堆栈: console.log(“x”) 进入调用堆栈,运行,然后我们将 console.log 发送到浏览器。之后,setTimeout(() =>{console.log(“y”);},3000);进入调用堆栈,因为第一个任务完成,然后转到第二个任务。

现在有件事,在阅读代码时,调用堆栈会检测到有一个 setTimeout 函数 已被设置,它不是 JavaScript 的一部分,而是 Web API 的一部分(参见图 JavaScript 运行时环境)并具有其特殊的特性。发生的情况是 setTimeout 触发 WEB API 并且由于 Web API 收到通知,该函数将从调用堆栈中弹出。

现在,Web API 启动一个三秒的计时器,知道它必须在 3 秒内完成任务。请记住这里,因为调用堆栈是空的,JavaScript 引擎继续到第 3 行,即 console.log(“z”);并执行它。这就是为什么我们得到结果 x,z 但我们在 Web API 中设置了三秒的 setTimeout。然后,三秒后,当时间限制结束时,setTimeout 运行并查看其中的内容,然后就完成了。完成后,Web API 将识别出它有 setTimeout 的 callback() 函数,并将其添加到 CALLBACK QUEUE 准备运行它。

我们来到最后一部分,即**事件循环*。这个函数会一直检查调用堆栈是否为空。当它为空并且 JavaScript 引擎中当前没有运行任何内容时,它将检查回调队列并使用 console.log(“z”) 找到我们的 **callback()* 函数,然后将其放入 CALL STACK 并运行。完成后,将其从调用堆栈中弹出。现在一切都是空的并得到结果 x z y。

结论:在这篇文章中,我们看到了很多有关幕后发生的事情的信息,以完全理解 JavaScript 逻辑以及同步和异步执行的任务。

希望这将帮助新的和高级 JavaScript 程序员享受在 ReactJS 或 AngularJS 等 JavaScript 相关框架中进行编码,因为这是理解高级逻辑的基础。

>快乐编码

参考文献

https://www.freecodecamp.org/news/how-javascript-works-behind-the-scenes。
https://www.simplilearn.com/tutorials/javascript-tutorial/callback-function-in-javascript#

以上是JavaScript 的底层是如何工作的?的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

前端热敏纸小票打印遇到乱码问题怎么办? 前端热敏纸小票打印遇到乱码问题怎么办? Apr 04, 2025 pm 02:42 PM

前端热敏纸小票打印的常见问题与解决方案在前端开发中,小票打印是一个常见的需求。然而,很多开发者在实...

神秘的JavaScript:它的作用以及为什么重要 神秘的JavaScript:它的作用以及为什么重要 Apr 09, 2025 am 12:07 AM

JavaScript是现代Web开发的基石,它的主要功能包括事件驱动编程、动态内容生成和异步编程。1)事件驱动编程允许网页根据用户操作动态变化。2)动态内容生成使得页面内容可以根据条件调整。3)异步编程确保用户界面不被阻塞。JavaScript广泛应用于网页交互、单页面应用和服务器端开发,极大地提升了用户体验和跨平台开发的灵活性。

谁得到更多的Python或JavaScript? 谁得到更多的Python或JavaScript? Apr 04, 2025 am 12:09 AM

Python和JavaScript开发者的薪资没有绝对的高低,具体取决于技能和行业需求。1.Python在数据科学和机器学习领域可能薪资更高。2.JavaScript在前端和全栈开发中需求大,薪资也可观。3.影响因素包括经验、地理位置、公司规模和特定技能。

如何使用JavaScript将具有相同ID的数组元素合并到一个对象中? 如何使用JavaScript将具有相同ID的数组元素合并到一个对象中? Apr 04, 2025 pm 05:09 PM

如何在JavaScript中将具有相同ID的数组元素合并到一个对象中?在处理数据时,我们常常会遇到需要将具有相同ID�...

JavaScript难以学习吗? JavaScript难以学习吗? Apr 03, 2025 am 12:20 AM

学习JavaScript不难,但有挑战。1)理解基础概念如变量、数据类型、函数等。2)掌握异步编程,通过事件循环实现。3)使用DOM操作和Promise处理异步请求。4)避免常见错误,使用调试技巧。5)优化性能,遵循最佳实践。

如何实现视差滚动和元素动画效果,像资生堂官网那样?
或者:
怎样才能像资生堂官网一样,实现页面滚动伴随的动画效果? 如何实现视差滚动和元素动画效果,像资生堂官网那样? 或者: 怎样才能像资生堂官网一样,实现页面滚动伴随的动画效果? Apr 04, 2025 pm 05:36 PM

实现视差滚动和元素动画效果的探讨本文将探讨如何实现类似资生堂官网(https://www.shiseido.co.jp/sb/wonderland/)中�...

JavaScript的演变:当前的趋势和未来前景 JavaScript的演变:当前的趋势和未来前景 Apr 10, 2025 am 09:33 AM

JavaScript的最新趋势包括TypeScript的崛起、现代框架和库的流行以及WebAssembly的应用。未来前景涵盖更强大的类型系统、服务器端JavaScript的发展、人工智能和机器学习的扩展以及物联网和边缘计算的潜力。

console.log输出结果差异:两次调用为何不同? console.log输出结果差异:两次调用为何不同? Apr 04, 2025 pm 05:12 PM

深入探讨console.log输出差异的根源本文将分析一段代码中console.log函数输出结果的差异,并解释其背后的原因。�...

See all articles