https://www.oschina.net/translate/how-does-javascript-actually-work-part-1

随着 JavaScript 变得越来越流行,很多团队在他们的堆栈中实现诸多层级的支持 - 前端、后端、混合应用程序、嵌入式设备等等。

本文是该系列文章的第一篇,旨在深入研究 JavaScript 及其实际工作原理:我们认为通过了解 JavaScript 的构建块以及它们如何一起协作的,你将能够编写更好的代码和应用。

如 GitHut 统计中所示,JavaScript 在 GitHub 中的活动存储库和总推送量方面位居前列。但它在其他分类中也未落后太多。

(查看 GitHub 语言统计最新版)

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

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

Tocy
翻译于 8个月前
1人顶
顶 翻译得不错哦!
 

概述

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

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

如果你对 JavaScript 比较生疏,本博客文章将帮助你理解为什么 JavaScript 相比与其他语言更“怪异”。

如果你是一位经验丰富的 JavaScript 开发人员,希望能够为你提供一些关于你每天使用的 JavaScript 运行时的实际工作情况的全新见解。

Tocy
翻译于 8个月前
1人顶
顶 翻译得不错哦!
 

JavaScript 引擎

Google V8 引擎是一个比较流行的 JavaScript 引擎示例。V8 引擎是在诸如 Chrome 和 Node.js 等内部使用的。下面是对其机制的一个简化视图:

该引擎包括两个主要组件:

* Memory Heap 内存堆 ——  这是内存分配发生的地方

* Call Stack 调用堆栈 ——  这是在你代码执行时栈帧存放的位置

Tocy
翻译于 8个月前
0人顶
顶 翻译得不错哦!
 

Runtime 运行时

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

那么,它们从哪里来呢?

事实证明,实际情况有点复杂。

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

然后,我们还有非常流行的事件循环和回调队列。

Tocy
翻译于 8个月前
0人顶
顶 翻译得不错哦!
 

Call Stack 调用堆栈

JavaScript 是一种单线程编程语言,这意味着它只有一个 Call Stack 。因此,它一次仅能做一件事。

Call Stack 是一个数据结构,它基本上记录了我们在程序中的所处的位置。如果我们进入一个函数,我们把它放在堆栈的顶部。如果我们从一个函数中返回,我们弹出堆栈的顶部。这是所有的堆栈可以做的东西。

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

function multiply(x, y) {
    return x * y;
}
function printSquare(x) {
    var s = multiply(x, x);
    console.log(s);
}
printSquare(5);

当引擎开始执行这个代码时,Call Stack 将会变成空的。之后,执行的步骤如下:

Call Stack 的每个入口被称为 Stack Frame(栈帧)。

这正是在抛出异常时如何构建 stack trace 的方法 - 这基本上是在异常发生时的 Call Stack 的状态。看看下面的代码:

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

如果这是在 Chrome 中执行的(假设这个代码在一个名为 foo.js 的文件中),那么会产生下面的 stack trace:

Tocy
翻译于 8个月前
1人顶
顶 翻译得不错哦!
 

“Blowing the stack”—当达到最大调用堆栈大小时,会发生这种情况。这可能会很容易发生,特别是如果你使用递归,而不是非常广泛地测试你的代码。看看这个示例代码:

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

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

然而,在某些情况下,调用堆栈中函数调用的数量超出了调用堆栈的实际大小,浏览器通过抛出一个错误(如下所示)来决定采取行动:

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

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

亚林瓜子
翻译于 8个月前
0人顶
顶 翻译得不错哦!
 
其它翻译版本(1)

并发&事件循环

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

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

而且这并不是唯一的问题。一旦你的浏览器开始在 Call Stack 中处理过多的任务,它可能会停止响应相当长的时间。大多数浏览器会通过触发错误来采取行动,询问你是否要终止网页。

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

Tocy
翻译于 8个月前
0人顶
顶 翻译得不错哦!
 

那么,我们如何执行大量代码而不阻塞 UI 使得浏览器无法响应? 解决方案就是异步回调。

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

同时,如果你在 JavaScript 应用程序中难以复现和理解问题,请查看 SessionStack 。 SessionStack 会记录你的 Web 应用中的所有东西:所有的 DOM 更改、用户交互、JavaScript 异常、堆栈跟踪、网络请求失败、调试消息等。

通过 SessionStack ,你可以以视频的方式重现问题,并查看发生在用户身上的所有事情。

这有一个免费的方案,所以你可以试试看。

解读 JavaScript 之引擎、运行时和堆栈调用的更多相关文章

  1. 解读JavaScript 之引擎、运行时和堆栈调用

    转载自开源中国 译者:Tocy, 凉凉_, 亚林瓜子, 离诌 原文链接 英文原文:How JavaScript works: an overview of the engine, the runtim ...

  2. 趣谈iOS运行时的方法调用原理

    一个成熟的计算机语言必然有丰富的体系,复杂的容错机制,处理逻辑以及判断逻辑.但这些复杂的逻辑都是围绕一个主线丰富和展开的,所以在学习计算机语言的时候,先掌握核心,然后了解其原理,明白程序语言设计的实质 ...

  3. C#运行时鼠标移动控件 - 调用Windows API(ReleaseCapture)

    [System.Runtime.InteropServices.DllImport("user32.dll")] public static extern bool SendMes ...

  4. OBJC运行时方法替换(Method swizzling)

    在上周associated objects一文中,我们开始探索Objective-C运行时的一些黑魔法.本周我们继续前行,来讨论可能是最受争议的运行时技术:method swizzling.   Me ...

  5. 基于 Java 2 运行时安全模型的线程协作--转

    在 Java 2 之前的版本,运行时的安全模型使用非常严格受限的沙箱模型(Sandbox).读者应该熟悉,Java 不受信的 Applet 代码就是基于这个严格受限的沙箱模型来提供运行时的安全检查.沙 ...

  6. Java运行时内存划分与垃圾回收--以及类加载机制基础

    ----JVM运行时内存划分----不同的区域存储的内容不同,职责因为不同1.方法区:被线程共享,存储被JVM加载的类的信息,常量,静态变量等2.运行时常量池:属于方法区的一部分,存放编译时期产生的字 ...

  7. ASP.NET运行时详解 生命周期入口分析

    说起ASP.NET的生命周期,网上有很多的介绍.之前也看了些这方面的博客,但我感觉很多程序猿像我一样,看的时候似乎明白,一段时间过后又忘了.所以,最近Heavi花了一段时间研究ASP.NET的源代码, ...

  8. Runtime运行时机制

    Runtime 又叫运行时,是一套底层的 C 语言 API,其为 iOS 内部的核心之一,我们平时编写的 OC 代码,底层都是基于它来实现的 我们需要了解的是 Objective-C 是一门动态语言, ...

  9. Cocoa 框架 For iOS(一) 框架的介绍,Objectivie-C运行时能力的解析等 (转载)

    http://blog.csdn.net/totogo2010/article/details/8081253 Cocoa框架是iOS应用程序的基础,了解Cocoa框架,对开发iOS应用有很大的帮助. ...

随机推荐

  1. thinkphp模板使用

    1.模板文件 就是个html,可以保存到View的Public文件夹下,比如叫base.html(参考onethink) <block name="a">a</b ...

  2. 前端 HTML 常用标签 head标签相关内容 style标签 定义内部样式表

    styple标签 <!-- 定义内部样式表 --> <style type="text/css"></style>

  3. finecms栏目文章页seo设置

    finecms栏目页和文章页默认的标题是页面title_二级栏目title_一级栏目title_网站名称(比如:finecms怎么设置标题_finecms二次开发_finecms_ytkah博客),如 ...

  4. Always On 集群监听创建失败问题

    创建SQL Server Always On监听失败如下 需要增加:1.登陆服务器的域账号创建计算机对象的权限,2.集群名称账号在域环境中创建计算机对象的权限 如果是重建监听:需要3.先删除原先的监听 ...

  5. ssh工具自动化命令

    SCP命令 scp [options] SRC... DEST/ 两种方式: scp [options] [user@]host:/sourcefile  /destpath scp [options ...

  6. python的__getitem__

    #这个方法返回与指定键相关的值.对序列来说,键应该是0~n-1的整数,其中n为序列的长度.对映射来说,键可以是任何类型. class Test(object): def __init__(self): ...

  7. win10升级后,无法ping通vmware的centos解决方法

    win10是lenovo thinkpad460上面的,是正版的.无法做设置,不让其自动升级.10月8日节后第一天上班,电脑要求更新,我就点更新. 结果就发现无法ping通vmware中的centos ...

  8. Redis:redis.conf配置

    redis.conf配置: 配置主要分为几类:基础.快照.复制.安全.限制.详细日志.虚拟内存.高级配置.文件包含 ##------------------------------------基础配置 ...

  9. Selenium基本使用(十二)测试报告生成

    报告目录结构 Reporter根目录 | |-------------LOGS |                                                | |         ...

  10. @responsebody 返回json

    添加jackson依赖 添加@ResponseBody 测试:  注意,如果输入中文,出现乱码现象,则需要@RequestMapping(value="/appinterface" ...