专栏首页京程一灯JavaScript的工作原理:引擎、运行时和调用堆栈 [每日前端夜话(0x13)]

JavaScript的工作原理:引擎、运行时和调用堆栈 [每日前端夜话(0x13)]

每日前端夜话0x13

每日前端夜话,陪你聊前端。

每天晚上18:00准时推送。

正文共:3098 字 9 图

预计阅读时间: 8 分钟

翻译:疯狂的技术宅 原文:https://blog.sessionstack.com/how-does-javascript-actually-work-part-1-b0bacc073cf

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

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

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

(查看最新的GitHub语言统计信息https://madnight.github.io/githut/)

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

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

概述

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

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

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

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

JavaScript引擎

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

引擎包含两个主要组件:

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

运行时

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

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

实际上这有点复杂。

所以尽管有了引擎,但是还需要很多东西。有一些叫做Web API的东西,它们是由浏览器提供的,比如DOM,AJAX,setTimeout等等。

此外还有非常受欢迎的事件循环和回调队列。

调用栈

JavaScript是一种单线程编程语言,这意味着它只有一个调用栈。 所以它一次只能做一件事。

调用栈是一种数据结构,它记录了当前程序中执行到的基本位置。 如果我们进入一个函数,会它放在栈的顶部。 如果我们从函数返回,就会将它从堆栈的顶部弹出。 这就是所有栈结构都可以做到的。

下面我们来看一个例子吧:

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

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

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

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

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

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

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

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

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

并发和事件循环

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

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

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

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

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

这一点在“如何运行JavaScript”教程的第2部分中有更详细的解释:“在V8引擎是怎么工作的:有关如何编写优化代码的5个技巧[https://blog.sessionstack.com/how-javascript-works-inside-the-v8-engine-5-tips-on-how-to-write-optimized-code-ac089e62b12e]”。

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

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

有一个免费的工具,不需要支付任何费用。 现在就可以试试[https://www.sessionstack.com/solutions/developers/?utm_source=medium&utm_medium=blog&utm_content=Post-1-overview-getStarted]。

本文分享自微信公众号 - 京程一灯(jingchengyideng),作者:京程一灯

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-01-15

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 我们应该为 JavaScript 重新命名吗?[每日前端夜话0xDA]

    非官方的,社区制作的JavaScript徽标。资料来源:https://github.com/voodootikigod/logo.js

    疯狂的技术宅
  • 2017 年学习 JavaScript 最好的书籍

    如果你不能成为一个好的 ReactJS,React Native,或者 Graphql 的开发者,那是因为你还没有熟练掌握JavaScript。每个月都会有新的...

    疯狂的技术宅
  • 企业级JavaScript:机遇,威胁与解决方案[每日前端夜话0x8E]

    Enterprise JavaScript: Opportunities, Threats, Solutions

    疯狂的技术宅
  • 如何正确学习JavaScript(写给非JavaScript程序员和编程新手)

    目录 不要这样学习JavaScript 本课程资源 1~2周(简介,数据类型,表达式和操作符) 3~4周(对象,数组,函数,DOM,jQuery) JavaSc...

    前朝楚水
  • 2017 最受欢迎的语言,第一不是 Java!

    Java技术栈
  • 学习笔记,JavaScript学习笔记(一)

    console.log("hello world!") 同样打印输出,不同是没有烦人的弹窗出现

    二爷
  • 从啥也不会到可以胜任最基本的JavaWeb工作,推荐给新人的学习路线(一)

    剽悍一小兔
  • JavaScript 诞生的这 20 年来,都发生了什么...

    今天在这里,我想跟大家推荐一篇极其具有学习及参考意义的文章:《JavaScript 20 年》。

    GitHubDaily
  • 学习纲要:JavaScript 基础概念

    Joel
  • 给新手的 JavaScript 介绍

    人与人沟通的语言称为自然语言,人与计算机沟通的语言称为编程语言。编程语言和自然语言的主要不同点是:自然语言表述的内容可以是有多种意思,编程语言表述的内容不会有歧...

    Joel

扫码关注云+社区

领取腾讯云代金券