本文转载自:众成翻译
译者:网络埋伏纪事
连接:http://www.zcfy.cc/article/3965
原文:https://blog.sessionstack.com/how-does-javascript-actually-work-part-1-b0bacc073cfjavascript
随着JavaScript愈来愈受欢迎,开发团队正在将其用在技术栈的各个方面,包括 - 前端、后端、混合应用、嵌入式设备等等。前端
如GitHut统计所示,JavaScript在GitHub中的活动存储库和总推送方面位于前列,在其余方面也不差。java
(查看最新的GitHub语言统计信息)。git
若是项目愈来愈依赖于JavaScript,这意味着开发人员必须更深刻地了解内部机制,才能利用语言和生态系统提供的全部技术,构建出惊艳的软件。github
事实证实,虽然有不少开发人员天天都在使用JavaScript,但并不知道它的工做机制。编程
几乎全部人都已经据说过V8引擎的概念,大多数人都知道JavaScript是单线程的,或者是使用回调队列。后端
在这篇文章中,咱们将详细介绍全部这些概念,并解释JavaScript的工做机制。经过了解这些细节,您将可以正确利用提供的API,编写更好的非阻塞应用程序。浏览器
若是您是一个JavaScript新手,此博文将帮助您了解为何JavaScript与其余语言相比是如此“怪异”。微信
而若是您是一位经验丰富的JavaScript开发人员,但愿可以提供与您天天使用的JavaScript运行时有关的一些新鲜看法。网络
JavaScript引擎的一个流行示例是Google的V8引擎。例如,V8引擎在Chrome和Node.js中使用。以下是它看起来像什么的一个简单视图:
引擎由两个主要组成部分组成:
浏览器中已经有几个几乎全部JavaScript开发人员都会使用的API(好比 setTimeout
)。不过,这些API不是由引擎提供的。
那么,它们是来自哪里呢?
事实证实,现实有点复杂。
因此,除了引擎之外,实际上还有更多东西。有一些由浏览器提供的,称为Web API的东西,好比DOM、AJAX、setTimeout等等。还有超受欢迎的事件循环和回调队列。
JavaScript是一种单线程编程语言,这意味着它只有一个调用栈。所以,它一次只能作一件事。
调用栈是一种数据结构,它基本上是记录了咱们处于程序中哪一个地方。若是单步执行进一个函数,就把该函数放在栈顶。若是从函数返回,就把它从栈顶弹出。这就是栈所作的事情。
下面咱们来看一个示例。看看下面的代码:
function multiply(x, y) { return x * y; } function printSquare(x) { var s = multiply(x, x); console.log(s); } printSquare(5);
引擎开始执行这段代码时,调用栈是空的。以后,步骤将是以下这样:
调用栈中的每一个条目称为栈帧。
而这正是在异常被抛出时,栈跟踪被构造的方式 - 当异常发生时,它基本上是调用栈的状态。看看下面的代码:
function foo() { throw new Error('SessionStack will help you resolve crashes :)'); } function bar() { foo(); } function start() { bar(); } start();
若是是在Chrome中执行这段代码(假设此代码位于一个名为foo.js的文件中),则会产生如下栈跟踪信息:
“爆栈” - 当达到最大调用栈大小时,就会发生这种状况。而且这很是容易发生,特别是若是使用递归而不充分测试代码时。请看以下示例代码:
function foo() { foo(); } foo();
当引擎开始执行这段代码时,它首先调用函数“foo”。不过,这个函数是递归的,而且开始调用自身而没有任何终止条件。因此在执行的每一个步骤中,相同的函数都被一次又一次地添加到调用栈中。看起来像这样:
然而,在某些时候,若是调用栈中的函数调用量超过了调用栈的实际大小,浏览器就会决定采起行动,抛出一个错误,看起来像这样:
在单个线程上运行代码可能很容易,由于您没必要处理在多线程环境中出现的复杂场景,例如死锁。
但在单线程上运行也有很大限制。因为JavaScript有一个调用栈,当事情缓慢时会发生什么?
当在调用栈中有函数调用须要大量时间才能处理完时,会发生什么?例如,假设想在浏览器中使用JavaScript进行一些复杂的图像转换。
你可能会问 - 这怎么就成了一个问题呢?缘由是,在调用堆有函数要执行的同时,浏览器实际上不能作任何事情 - 它被阻塞了。这意味着浏览器没法渲染,它不能运行任何其余代码,它只是卡住了。若是想在应用中有流畅的UI,这会出问题。
而这不是惟一的问题。一旦浏览器开始处理调用栈中的许多任务,它可能会中止响应很长时间。大多数浏览器经过引起一个错误来采起行动,询问您是否要终止网页。
如今,这不是最好的用户体验,对吧?
那么,如何执行繁重的代码,而不阻塞UI而且不会使浏览器无响应呢?好吧,解决方案是异步回调。
我将在教程的第2部分中详细介绍。敬请关注 :)
欢迎关注个人公众号,关注前端文章: