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

2017-10-19 09:11


这篇文章旨在成为系列中第一个旨在深入挖掘JavaScript及其实际工作的系列文章:我们认为,通过了解JavaScript的构建方式以及它们如何共同发挥,您将能够编写更好的代码和应用。

GitHut统计所示,JavaScript在GitHub中的活动存储库和总推送方面位于顶部。在其他类别中也不会落后于很多。

 

如果项目越来越依赖JavaScript,这意味着开发人员必须利用语言和生态系统提供的所有内容来更深入地了解内部内容,以便构建出惊人的软件。

事实证明,有很多开发人员每天都在使用JavaScript,但不知道什么会发生什么。

概观

几乎所有人都已经听说过V8引擎的概念,大多数人都知道JavaScript是单线程的,或者是使用回调队列。

在这篇文章中,我们将详细介绍所有这些概念,并解释JavaScript如何运行。通过了解这些细节,您将能够编写更好的非阻塞应用程序,正确利用提供的API。

如果您对JavaScript相对较新,此博文将帮助您了解为什么JavaScript与其他语言相比是如此“奇怪”。

如果您是一位经验丰富的JavaScript开发人员,希望能够为您提供一些新的见解,了解您每天使用的JavaScript运行时间是否真的有效。

JavaScript引擎

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

 

引擎包括两个主要组件:
*内存堆 - 这是内存分配发生的地方
*调用堆栈 - 这是您的堆栈帧的位置,因为您的代码执行

运行时

浏览器中已经有几个JavaScript开发人员使用的API(例如“setTimeout”)。然而,引擎不提供这些API。

那么他们从哪里来?

事实证明,现实有点复杂。

 

所以,我们有引擎,但实际上还有更多。我们有一些称为Web API的东西,由浏览器提供,如DOM,AJAX,setTimeout等等。

然后,我们有如此流行的事件循环回调队列

呼叫堆栈

JavaScript是单线程编程语言,这意味着它有一个单一的调用堆栈。因此,它可以一次做一件事。

调用堆栈是一个数据结构,它基本上记录了程序中的哪些。如果我们进入一个函数,我们把它放在堆栈的顶部。如果我们从一个函数返回,我们弹出堆栈的顶部。这就是堆栈可以做的。

我们来看一个例子。看看下面的代码:

函数乘法(x,y){ 
    return x * y; 
}
function printSquare(x){ 
    var s = multiply(x,x); 
    的console.log(一个或多个); 
}
printSquare(5);

当引擎开始执行此代码时,调用堆栈将为空。之后,步骤如下:

 

调用堆栈中的每个条目称为堆栈帧

这正是抛出异常时构造堆栈跟踪的方式 - 当异常发生时,它基本上是调用堆栈的状态。看看下面的代码:

function foo(){ 
    throw new Error('SessionStack will help you resolve crash :)'); 
}
function bar(){ 
    foo(); 
}
function start(){ 
    bar(); 
}
开始();

如果这是在Chrome中执行的(假设此代码位于一个名为foo.js的文件中),则会产生以下堆栈跟踪:

 

“ 吹起堆叠 ” - 当您达到最大呼叫堆栈大小时,会发生这种情况。这可能会很容易发生,特别是如果您在不经常地对代码进行测试的情况下使用递归。看看这个示例代码:

function foo(){ 
    foo(); 
}
FOO();

当引擎开始执行这个代码时,它首先调用函数“foo”。然而,这个函数是递归的,并且开始调用自身而没有任何终止条件。所以在执行的每个步骤中,相同的功能被一次又一次地添加到调用堆栈中。看起来像这样:

 

然而,在某些时候,调用堆栈中的函数调用次数超过了调用堆栈的实际大小,并且浏览器决定采取行动,通过抛出一个错误,看起来像这样:

 

在单个线程上运行代码可能非常容易,因为您不必处理在多线程环境中出现的复杂场景,例如死锁。

但是在单线程上运行也是非常有限的。由于JavaScript有一个调用堆栈,当事情缓慢时会发生什么?

并发和事件循环

当您在调用堆栈中进行函数调用需要大量时间才能处理时会发生什么?例如,假设您想在浏览器中使用JavaScript进行一些复杂的图像转换。

你可能会问 - 为什么这甚至是一个问题?问题是,虽然调用堆栈具有执行的功能,但浏览器实际上不能做任何事情 - 它被阻止。这意味着浏览器无法渲染,它不能运行任何其他代码,它只是卡住了。如果您想要在应用中使用流畅的UI,这会产生问题。

这不是唯一的问题。一旦您的浏览器开始处理Call Stack中的这么多任务,它可能会停止响应很长时间。大多数浏览器通过提出错误来采取行动,询问您是否要终止网页。

 

现在,这不是最好的用户体验,是吗?

那么,如何在不阻塞UI并使浏览器无响应的情况下执行繁重的代码呢?那么解决方案是异步回调

这将在“JavaScript如何实际工作”教程的第2部分中更详细地解释:“我没有V8引擎+5个关于如何编写优化代码的技巧 ”。

在此期间,如果您在JavaScript应用程序中难以重现和理解问题,请查看SessionStackSessionStack记录您的Web应用程序中的所有内容:所有DOM更改,用户交互,JavaScript异常,堆栈跟踪,失败的网络请求和调试消息。

使用SessionStack,您可以将Web应用中的问题重播为视频,并查看用户发生的一切。

服务支持

我们珍惜您每一次在线询盘,有问必答,用专业的态度,贴心的服务。

让您真正感受到我们的与众不同!

合作流程
合作流程

重庆网站建设流程从提出需求到网站建设报价,再到网站建设,每一步都是规范和专业的。

常见问题
常见问题

什么是网站定制?网站报价如何?网站常见问题。

常见问题
售后保障

网站建设不难,难的是一如既往的热情服务及技术支持。我们知道:做网站就是做服务,就是做售后。