JavaScript的工作原理:引擎,运行时和调用堆栈

栏目: JavaScript · 发布时间: 7年前

内容简介:翻译:疯狂的技术宅原文:随着JavaScript变得越来越流行,越来越多的团队正在利用他们为技术栈中做多个级别的支持:前端、后端、混合应用、嵌入式设备等等。

翻译:疯狂的技术宅

原文: blog.sessionstack.com/how-does-ja…

随着JavaScript变得越来越流行,越来越多的团队正在利用他们为技术栈中做多个级别的支持:前端、后端、混合应用、嵌入式设备等等。

本文旨在深入挖掘JavaScript及其实际的工作方式:我们认为通过了解JavaScript的构建块以及它们如何发挥作用,你将能够编写更好的代码和应用。 我们还将分享自己在构建SessionStack时使用的一些经验和规范,这是一个轻量级JavaScript应用,必须具有强大功能和高性能才能保持竞争力。

正如GitHut stats所示,JavaScript在GitHub中的Active Repositories和Total Pushes方面处于领先地位。 它也不会落后于其他语言。

JavaScript的工作原理:引擎,运行时和调用堆栈

查看最新的GitHub语言统计信息 )。

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

事实证明,有很多开发人员每天都在使用JavaScript,却不了解背后究竟发生了些什么。

概述

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

在本文中,我们将详细介绍这些概念,并解释JavaScript实际运行的方式。 通过了解这些详细信息,你将能够正确地利用其所提供的API编写更好的、非阻塞的应用,这些应用正确地利用了所提供的API。

如果你对JavaScript比较陌生,那么本文将帮助你理解为什么JavaScript与其他语言相比是如此的“奇怪”。

如果你是一位经验丰富的JavaScript开发者,尽管你每天使用它,但仍然希望它能够为你提供一些关于JavaScript运行时工作方式方面的新见解。

JavaScript引擎

一个很流行的JavaScript引擎是Google的V8引擎。 V8引擎被用于Chrome和Node.js。 这是一个非常简化的示意图:

JavaScript的工作原理:引擎,运行时和调用堆栈

引擎包含两个主要组件:

  • 内存堆 - 这是进行内存分配的地方
  • 调用栈 - 这是你的代码执行时堆栈帧的位置

运行时

这是几乎所有JavaScript开发人员在浏览器中都使用过的API(例如“setTimeout”)。 但是引擎并不提供这些API。

那么,他们究竟来自哪里?

实际上这有点复杂。

JavaScript的工作原理:引擎,运行时和调用堆栈

所以尽管有了引擎,但是还需要很多东西。有一些叫做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);
复制代码

当引擎开始执行上面的代码时,调用堆栈将为空。 接下来的步骤如下:

JavaScript的工作原理:引擎,运行时和调用堆栈

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

这是在抛出异常时堆栈跟踪的构造方式 —— 当异常发生时调用堆栈的大致状态。 接下来看下面这段代码:

function foo() {
    throw new Error('SessionStack will help you resolve crashes :)');
}
function bar() {
    foo();
}
function start() {
    bar();
}
start();
复制代码

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

JavaScript的工作原理:引擎,运行时和调用堆栈

当达到最大调用堆栈大小时会发生“ Blowing the stack ”这种情况。 这种情况是很容易发生的,尤其是在你使用递归而没有充分地测试你的代码时。 看一下这段代码:

function foo() {
    foo();
}
foo();
复制代码

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

JavaScript的工作原理:引擎,运行时和调用堆栈

在某些时候,如果调用栈中的函数调用数量超过了它的实际大小,浏览器就会抛出错误,该错误看起来像这样:

JavaScript的工作原理:引擎,运行时和调用堆栈

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

但是跑在单个线程上也是非常受限的。 由于JavaScript只有一个调用, 当处理变慢时会发生什么?

并发和事件循环

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

你可能会问:这也算是一个问题? 实际上虽然调用栈具有执行功能,但浏览器实并没有办法执行其他的操作,因为它会被阻止。 这意味着浏览器将无法进行渲染,也无法运行任何其他代码,它只是被卡住了。 如果你想在自己的应用中产生流畅的UI,在这里将会出现问题。

这并不是唯一的问题。 一旦你的浏览器开始在调用栈中处理如此之多的任务,它可能会在相当长的时间内停止响应。 大多数浏览器将会通过引发错误来解决这个问题,询问你是否要终止网页的运行。

JavaScript的工作原理:引擎,运行时和调用堆栈

所以这并不是最佳的用户体验,对吗?

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

这一点在“如何运行JavaScript”教程的第2部分中有更详细的解释:“在V8引擎是怎么工作的:有关如何编写优化代码的5个技巧( blog.sessionstack.com/how-javascr… )”。

与此同时,如果你在JavaScript应用程序中遇到难以复制和理解的问题,可以试试SessionStack( www.sessionstack.com/?utm_source… )。 SessionStack会记录Web应用中所有的内容:所有的DOM修改、用户交互、JavaScript异常、堆栈跟踪、网络请求失败和调试消息。

通过SessionStack,你可以将网络应用中的问题重现,并查看发生的所有事情。

有一个免费的工具,不需要支付任何费用。 现在就可以试试( www.sessionstack.com/solutions/d… )。

JavaScript的工作原理:引擎,运行时和调用堆栈

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Learning PHP, MySQL, and JavaScript

Learning PHP, MySQL, and JavaScript

Robin Nixon / O'Reilly Media / 2009-7-21 / USD 39.99

Learn how to create responsive, data-driven websites with PHP, MySQL, and JavaScript - whether or not you know how to program. This simple, streamlined guide explains how the powerful combination of P......一起来看看 《Learning PHP, MySQL, and JavaScript》 这本书的介绍吧!

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具