概述

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

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

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

如果你是一个有经验的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和不使浏览器失去响应的情况下执行大量代码呢?解决方案是异步回调。

本文内容来自微信公众号

JavaScript是如何工作的01:引擎,运行时和调用堆栈的概述!的更多相关文章

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

    摘要: 理解JS执行原理. 原文:JavaScript是如何工作的:引擎,运行时和调用堆栈的概述! 作者:前端小智 Fundebug经授权转载,版权归原作者所有. 本文是旨在深入研究JavaScrip ...

  2. JavaScript 对引擎、运行时、调用堆栈的概述理解

    JavaScript 对引擎.运行时.调用堆栈的概述理解  随着JavaScript越来越流行,越来越多的团队广泛的把JavaScript应用到前端.后台.hybrid 应用.嵌入式等等领域. 这篇文 ...

  3. JavaScript是如何工作的:引擎,运行时间以及调用栈的概述

    JavaScript是如何工作的:引擎,运行时以及调用栈的概述 原文:How JavaScript works: an overview of the engine, the runtime, and ...

  4. Java 内存管理、JVM 工作原理与 Java 运行时系统

    Java 虚拟机规范中说明:所有的对象实例(all class instances)以及数组都要在堆上分配: the heap is the runtime data area from which ...

  5. gdb运行时结合汇编堆栈分析

    一.从源代码文件到可执行文件         从C文件到可执行文件,一般来说需要两步,先将每个C文件编译成.o文件,再把多个.o文件和链接库一起链接成可执行文件.但具体来说,其实是分为四步,下面以ex ...

  6. Android webview 运行时不调用系统自带浏览器

    WebView mobView = new WebView(this); mobView.loadUrl("http://www.csdn.net"); WebSettings w ...

  7. JavaScript 是如何工作的:JavaScript 的共享传递和按值传递

    摘要: 原始数据类型和引用数据类型的副本作为参数传递给函数. 原文:JavaScript 是如何工作的:JavaScript 的共享传递和按值传递 作者:前端小智 Fundebug经授权转载,版权归原 ...

  8. JavaScript 是如何工作的:JavaScript 的内存模型

    摘要: 从内存角度理解 let 和 const 的意义. 原文:JavaScript 是如何工作的:JavaScript 的内存模型 作者:前端小智 Fundebug经授权转载,版权归原作者所有. 这 ...

  9. JavaScript是如何工作的:编写自己的Web开发框架 + React及其虚拟DOM原理

    这是专门探索 JavaScript 及其所构建的组件的系列文章的第 19 篇. 如果你错过了前面的章节,可以在这里找到它们: JavaScript 是如何工作的:引擎,运行时和调用堆栈的概述! Jav ...

随机推荐

  1. 转:路由 router-view

    原文链接: 路由 router-view 路由,其实就是指向的意思,当我点击页面上的home按钮时,页面中就要显示home的内容,如果点击页面上的about 按钮,页面中就要显示about 的内容.H ...

  2. PAT(A) 1148 Werewolf - Simple Version(Java)逻辑推理

    题目链接:1148 Werewolf - Simple Version (20 point(s)) Description Werewolf(狼人杀) is a game in which the p ...

  3. WUSTOJ 1325: Distance(Java)坐标计算

    题目链接:1325: Distance Description There is a battle field. It is a square with the side length 100 mil ...

  4. C# 简单的区块链实现

    1.项目配置 首先新建一个 Asp.Net Core 项目,然后选择 Empty Project(空项目) 类型,建立完成后无需进行任何配置. 2.数据模型 这里我们来创建一个具体的区块数据模型,使用 ...

  5. thrift原理与架构

    是什么: 一个RPC框架.

  6. 是否应该学习qt源码(碰到问题的时候,或者文档对函数描述不清楚的时候,可以看一下)

    是否应该学习qt源码 如果你想调用某个函数,但是文档并没有清晰描述这个函数的功能的时候,你就需要去阅读源码,看看Qt究竟是怎么实现的.比如用QNetworkAccessManager发送一个QHttp ...

  7. 在论坛中出现的比较难的sql问题:21(递归问题 检索某个节点下所有叶子节点)

    原文:在论坛中出现的比较难的sql问题:21(递归问题 检索某个节点下所有叶子节点) 最近,在论坛中,遇到了不少比较难的sql问题,虽然自己都能解决,但发现过几天后,就记不起来了,也忘记解决的方法了. ...

  8. Visual Studio 2013/15/17小技巧

    1.Ctrl + F10 可以直接运行到光标处,而不用F10 逐过程 F11 逐语句了 2.当有多个断点时,按F5可以切换到下一个断点. 3.Ctrl+Shift+空格 显示函数签名,上下键可以查看所 ...

  9. SQL Server存储过程中变量使用函数调用变量

    USE  DB名称GO SET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGO . CREATE   PROCEDURE     存储过程名 @formID   n ...

  10. https、加密安全

    1.Https HTTPS在传输的过程中会涉及到三个密钥: 服务器端的公钥和私钥,用来进行非对称加密 客户端生成的随机密钥,用来进行对称加密 一个HTTPS请求实际上包含了两次HTTP传输,可以细分为 ...