原做者:blog.sessionstack.com/@zlatkovjavascript
随着JS变得愈来愈流行,开发团队们在多个级别的堆栈中都借力于js的支持- 前端,后台,混合式应用开发,嵌入式设备等等。前端
这篇博文旨是咱们深刻挖掘JavaScript和其工做原理的系列文章的第一篇:咱们认为经过了解JavaScript的构建块和他们是如何共同发挥做用的,你能写出更好的代码和应用。咱们也会分享咱们在构建的一个轻量级的但必须具备强大和高性能的特色才能保持竞争力的JavaScript应用SessionStack时的一些经验法则。java
正如GitHut Stats上的数据所示,JavaScript在github上的包活跃度和推送量居于领先地位。它也没有落后于其余类别的库。node
(查看github上最新的统计信息)git
若是项目依赖JavaScript愈来愈多,则意味着开发者不得不用对其内部原理愈来愈深的理解来利用好语言和其生态系统所提供的一切以构建使人惊奇的软件。github
事实证实,虽然有大量的开发者天天都会使用JavaScript,可是他们并不知道引擎盖下发生了什么。编程
几乎人人都已经据说过V8引擎这个概念,大多数人也知道JavaScript是单线程或使用回调队列。api
在本文中,咱们将会详细地了解这些概念和解释JavaScript其实是怎样运行的。知道了这些细节后,你讲可以写出更好的、正确使用了提供的api的非阻塞的应用。浏览器
若是你对JavaScript这么语言还比较陌生,那么本文能够帮助你理解为甚JavaScript和其余语言相比这么“神奇”。bash
若是你已是一名富有经验的JavaScript开发者,那咱们但愿本文能在你天天都在使用的JavaScript运行时到底如何工做的问题上提供一些新的看法。
JavaScript引擎的一个流行实例是谷歌的V8引擎,V8引擎运用在谷歌浏览器和node.js内部。这里有一个简化的视图:
引擎由主要由两部分组成:
* 内存堆—这里是内存分配发生的地方。
* 调用堆栈—这是当你的代码执行时堆栈帧的位置
浏览器中有许多api几乎每一个JavaScript开发者都使用过(好比“setTimeout”),然而,这些api并非引擎提供的。
那么,他们是哪儿来的呢?
事实上,状况有些复杂。
因此,咱们不只有引擎,还有更多东西。咱们有浏览器提供的Web APIs,好比,DOM, AJAX, setTimeout 等等。
此外,还有如此受欢迎的事件循环和回调队列。
JavaScript是一门单线程的编程语言,这意味着它只有一个堆栈(Call Stack),一次只能作一件事情。
堆栈是一种用来记录代码在程序中的位置的数据结构,当咱们运行到一个函数调用时,咱们把它放在堆栈的顶部,当函数运行完之后,咱们把它从堆栈的顶部移除(出栈)。这就是堆栈所能作的所有了。
让咱们来看个例子,看看下面的代码:
当引擎开始执行代码的时候,堆栈里面是空的。而后,会按下面这几个步骤运行:
每一次进栈被称为一个栈帧(Stack Frame)。
这正是抛出异常时堆栈跟踪的构造方式 — 它基本上是异常发生时调用堆栈的状态。看看下面的代码:
若是在谷歌浏览器中执行(假如是在一个叫foo.js的文件里),将会发生如下的堆栈跟踪:
“堆栈溢出(Blowing the stack)”—当达到堆栈调用最大容量时会发生这种状况。要发生这种状况也很简单,尤为是当你使用递归而没有普遍地测试你的代码的时候。看看下面的例子:
function foo(){
foo()
};
foo();
复制代码
当引擎开始执行这段代码的时候,它开始调用‘foo’函数,然而‘foo’是一个递归它以调用它自己开始,而且没有任何终止条件。因此,执行的每一步,这个函数会一遍又一遍地进栈。看起来就像这样:
但到了必定程度,函数调用的数量超出了堆栈自己的容量,浏览器就会采起行动,抛出一个错误。相似这样:
在单线程中运行代码会很是简单,由于你不用处理一些发生在多线程环境里的复杂场景。好比:死锁(deadlocks)
可是在单线程中运行也有不少限制,因为JavaScript只有一个Call Stack,那么当事情变慢时会发生什么?
若是在调用堆栈中有函数调用须要花费大量时间才能处理,会发生什么?好比,想象一下你想用JavaScript在浏览器上作一些复杂的图片转换。
你或许会问—为何这是一个问题?问题就是当堆栈里有函数须要执行的时候,浏览器实际上任何其余事都作不了—它被阻塞了。这就意味着浏览器不能渲染,不能执行任何其余代码,只能卡住了。若是你想要在你的应用中有流畅的UI,这就是个问题了。
这还不只仅是惟一的问题。一旦浏览器要在堆栈中处理不少任务的时候,可能会很长一段时间没有响应。这时候大多数浏览器都会抛出错误,询问你是否要终止该网页。
如今,这不是最好的用户体验,对吗?
因此,咱们如何既能执行繁重的代码同时也不会阻塞UI渲染或致使浏览器不响应呢?well,解决办法就是异步回调。
这在“JavaScript如何工做”的第二部分教程“V8引擎内部+关于如何编写优化代码的5个技巧”(个人译文)中有更详细的解释。
同时,若是你很难再现和理解你的JavaScript应用中出现的问题,你能够看看SessionStack.
SessionStack记录了你的应用中发生的任何事情:全部DOM更改,用户交互,JavaScript异常,堆栈跟踪,失败的网络请求和调试消息。
使用SessionStack,你能够将网络应用中的问题做为视频重播,并查看用户发生的全部事情。
这儿有一个免费的方案,不须要任何的通行证。Get Start Now。