JavaScript是如何工做的:引擎,运行时和调用堆栈的概述!

阿里云最近在作活动,低至2折,有兴趣能够看看:
https://promotion.aliyun.com/...

为了保证的可读性,本文采用意译而非直译。javascript

本文是旨在深刻研究JavaScript及其实际工做原理的系列文章中的第一篇:咱们认为经过了解JavaScript的构建块以及它们是如何工做的,将可以编写更好的代码和应用程序。咱们还将分享构建 SeStHealsStad 时使用的一些经验法则,这是一个轻量级的 JavaScript 应用程序,必须保持健壮和高性能以保持竞争力。html

想阅读更多优质文章请猛戳GitHub博客,一年百来篇优质文章等着你!前端

GitHut 统计 数据所示,在GitHub中的活动存储库和总推送方面,JavaScript处于顶部。它也不落后于其余类别。java

图片描述

若是项目愈来愈依赖于 JavaScript,这意味着开发人员必须利用语言和生态系统提供的全部内容,对内部进行更深刻的了解,以便构建出色的软件。git

事实证实,有不少开发人员天天都在使用JavaScript,但殊不知道背后发生了什么。github

概述

几乎每一个人都已经据说过 V8 引擎,大多数人都知道 JavaScript 是单线程的,或者它使用的是回调队列。web

在本文中,咱们将详细介绍这些概念,并解释 JavaScrip 实际如何运行。经过了解这些细节,你将可以适当地利用所提供的 API 来编写更好的、非阻塞的应用程序。编程

若是您对JavaScript还比较陌生,那么本文将帮助您理解为何JavaScript与其余语言相好比此“怪异”。segmentfault

若是你是一个有经验的JavaScript开发人员,但愿它能让您对天天使用的JavaScript运行时的实际工做方式有一些新的看法。浏览器

JavaScript引擎

JavaScript引擎的一个流行示例是Google的V8引擎。例如,在Chrome和Node.js中使用V8引擎,下面是一个很是简化的视图:

图片描述

V8引擎由两个主要部件组成:

  • emory Heap(内存堆) — 内存分配地址的地方
  • Call Stack(调用堆栈) — 代码执行的地方

Runtime(运行时)

有些浏览器的 API 常常被使用到(好比说:setTimeout),可是,这些 API 却不是引擎提供的。那么,他们是从哪儿来的呢?事实上这里面实际状况有点复杂。

图片描述

因此说咱们还有不少引擎以外的 API,咱们把这些称为浏览器提供 API 称为 Web API,好比说 DOM、AJAX、setTimeout等等。

而后咱们还拥有如此流行的事件循环和回调队列。

调用栈

JavaScript是一种单线程编程语言,这意味着它只有一个调用堆栈。所以,它一次只能作一件事。

调用栈是一种数据结构,它记录了咱们在程序中的位置。若是咱们运行到一个函数,它就会将其放置到栈顶,当从这个函数返回的时候,就会将这个函数从栈顶弹出,这就是调用栈作的事情。

来个栗子:

图片描述

当程序开始执行的时候,调用栈是空的,而后,步骤以下:

图片描述

每个进入调用栈的都称为调用帧。

这能清楚的知道当异常发生的时候堆栈追踪是怎么被构造的,堆栈的状态是如何的,让咱们看一下下面的代码:

图片描述

若是这发生在 Chrome 里(假设这段代码实在一个名为 foo.js 的文件中),那么将会生成如下的堆栈追踪:

图片描述

"堆栈溢出",当你达到调用栈最大的大小的时候就会发生这种状况,并且这至关容易发生,特别是在你写递归的时候却没有全方位的测试它。咱们来看看下面的代码:

图片描述

当引擎开始执行这段代码时,它首先调用函数“foo”。然而,这个函数是递归的,而且在没有任何终止条件的状况下开始调用本身。所以,在执行的每一步中,相同的函数都会被一次又一次地添加到调用堆栈中,以下所示:

图片描述

然而,在某些时候,调用堆栈中的函数调用数量超过了调用堆栈的实际大小,浏览器决定采起行动,抛出一个错误,它多是这样的:

图片描述

在单个线程上运行代码很容易,由于你没必要处理在多线程环境中出现的复杂场景——例如死锁。
可是在一个线程上运行也很是有限制,因为 JavaScript 只有一个调用堆栈,当某段代码运行变慢时会发生什么?

并发与事件循环

当调用堆栈中的函数调用须要花费大量时间来处理时会发生什么状况? 例如,假设你但愿在浏览器中使用JavaScript进行一些复杂的图像转换。

你可能会问-为何这是一个问题?问题是,当调用堆栈有函数要执行时,浏览器实际上不能作任何其余事情——它被阻塞了,这意味着浏览器不能呈现,它不能运行任何其余代码,它只是卡住了,若是你想在应用中使用流畅的页面效果,这就会产生问题。

并且这不是惟一的问题,一旦你的浏览器开始处理调用栈中的众多任务,它可能会中止响应至关长一段时间。大多数浏览器都会这么作,报一个错误,询问你是否想终止 web 页面。

图片描述

这并非最好的用户体验,不是吗?

那么,咱们怎样才能在不阻塞UI和不使浏览器失去响应的状况下执行大量代码呢?解决方案是异步回调。

这个在下一篇说明,我尽快把原做者的内容整理好!

代码部署后可能存在的BUG无法实时知道,过后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给你们推荐一个好用的BUG监控工具 Fundebug

原文:https://blog.sessionstack.com...

你的点赞是我持续分享好东西的动力,欢迎点赞!

交流

干货系列文章汇总以下,以为不错点个Star,欢迎 加群 互相学习。

https://github.com/qq44924588...

我是小智,公众号「大迁世界」做者,对前端技术保持学习爱好者。我会常常分享本身所学所看的干货,在进阶的路上,共勉!

关注公众号,后台回复福利,便可看到福利,你懂的。

clipboard.png