Javascript 的工作原理:引擎、运行时和调用堆栈概述

简介: 随着 Javascript 越来越流行,使其应用的场景越来越多,不仅限于前端,可以是后端、混合应用程序、嵌入式设备等等,于是就有了大前端的叫法。本文开始带大家一起回顾总结 Javascript 的构建块以及它们是如何协同工作,理解其原理,将有助于编写更优的代码。

随着 Javascript 越来越流行,使其应用的场景越来越多,不仅限于前端,可以是后端、混合应用程序、嵌入式设备等等,于是就有了大前端的叫法。本文开始带大家一起回顾总结 Javascript 的构建块以及它们是如何协同工作,理解其原理,将有助于编写更优的代码。

概述

大部份人都听说过 V8 引擎,都知道 Javascript 是单线程的,或者它使用的是回调队列。下面将围绕这些概念展开,并解释 Javascript 的实际运行方式。通过了解这些细节,能够编写更好的、无阻塞的应用程序,并正确利用所提供的 API。

Javascript 引擎

Javascript 引擎中最流行的莫过于 Google 开发的 V8 引擎,可以用于 Chrome 和 Node.js。下面是它的架构图:

image.png

引擎由两个主要部份组成:

  • 内存堆:内存分配发生的地方
  • 调用栈:代码执行时的堆栈帧所在的地方

Runtime

浏览器中的 API 几乎大部份 Javascript 开发工程师都使用过(例如:setTimeout)。但是,这些 API 并不是由 Javascript 引擎提供的。那么,它们是谁提供的呢?来自哪里?

image.png

因此除了引擎,实际上还有很多,如浏览器提供的 Web Api,如:DOMAJAXsetTimeout 等等。

然后,还有非常流行的  event loopcallback queue

调用栈

Javascript 是一种单线程编程语言,这意味着它只有一个调用堆栈,因此它一次只能做一件事。

调用栈是一种数据结构,它基本上记录了在程序中的位置。如果进入一个函数,会将它放在栈顶。如果从一个函数返回,会从栈顶推出。这是堆栈可以做的所有事情。

看看下面的代码:

const multiply = (x, y) => {
    return x * y;
};
const square = (x) => {
    const s = multiply(x, x);
    console.log(s);
};
square(6);

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

image.png

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

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

function foo() {
    throw new Error("foo异常抛出!");
}
function bar() {
    foo();
}
function start() {
    bar();
}
start();

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

image.png

Blowing the stack :当达到最大调用堆栈大小时会发生这种情况,这种情况很容易发生,特别是如果使用递归而没有全面测试。看看这个示例代码:

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

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

image.png

然而,在某些时候,调用堆栈中的函数调用数量超过了调用堆栈的实际大小,浏览器决定采取行动,抛出一个错误,它可能如下所示:

image.png

在单线程上运行代码非常容易出现这种情况。

并发和事件循环

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

如果调用堆栈有要执行的函数,浏览器实际上不能做任何其他事情,这个时候处于阻塞状态。这意味着浏览器无法渲染,无法运行任何其他代码,出现卡住的现象。如果想在应用中使用流畅的 UI,就需要避免阻塞情况的出现。

如果浏览器开始在调用堆栈中处理很多的任务,它可能会在很长一段时间内停止响应,大多数浏览器通过触发错误来终止此类行动,并询问是否要终止网页。

总结

本文简单介绍了 Javascript 的引擎、运行时和调用堆栈,调用堆栈阻塞、卡死的情况将在接下来的《深入了解V8引擎》介绍优化技巧。


相关文章
|
1月前
|
Web App开发 JavaScript 前端开发
Node.js 是一种基于 Chrome V8 引擎的后端开发技术,以其高效、灵活著称。本文将介绍 Node.js 的基础概念
Node.js 是一种基于 Chrome V8 引擎的后端开发技术,以其高效、灵活著称。本文将介绍 Node.js 的基础概念,包括事件驱动、单线程模型和模块系统;探讨其安装配置、核心模块使用、实战应用如搭建 Web 服务器、文件操作及实时通信;分析项目结构与开发流程,讨论其优势与挑战,并通过案例展示 Node.js 在实际项目中的应用,旨在帮助开发者更好地掌握这一强大工具。
46 1
|
2月前
|
自然语言处理 JavaScript 前端开发
深入理解JavaScript中的闭包:原理与实战
【10月更文挑战第12天】深入理解JavaScript中的闭包:原理与实战
|
24天前
|
机器学习/深度学习 JavaScript Cloud Native
Node.js作为一种快速、可扩展的服务器端运行时环境
Node.js作为一种快速、可扩展的服务器端运行时环境
35 8
|
1月前
|
JavaScript 前端开发 安全
探索Deno:新一代JavaScript/TypeScript运行时
Deno是由Node.js创始人Ryan Dahl发起的新一代JavaScript/TypeScript运行时,旨在提升安全性、模块化和性能。本文介绍了Deno的核心特性,如内置TypeScript支持、强大的模块系统、权限管理和测试工具,以及开发技巧,帮助开发者构建更安全、高效的Web应用。
|
1月前
|
缓存 前端开发 JavaScript
JavaScript前端路由的实现原理及其在单页应用中的重要性,涵盖前端路由概念、基本原理、常见实现方式
本文深入解析了JavaScript前端路由的实现原理及其在单页应用中的重要性,涵盖前端路由概念、基本原理、常见实现方式(Hash路由和History路由)、优点及挑战,并通过实际案例分析,帮助开发者更好地理解和应用这一关键技术,提升用户体验。
74 1
|
1月前
|
监控 JavaScript 算法
深度剖析 Vue.js 响应式原理:从数据劫持到视图更新的全流程详解
本文深入解析Vue.js的响应式机制,从数据劫持到视图更新的全过程,详细讲解了其实现原理和运作流程。
|
1月前
|
机器学习/深度学习 自然语言处理 前端开发
前端神经网络入门:Brain.js - 详细介绍和对比不同的实现 - CNN、RNN、DNN、FFNN -无需准备环境打开浏览器即可测试运行-支持WebGPU加速
本文介绍了如何使用 JavaScript 神经网络库 **Brain.js** 实现不同类型的神经网络,包括前馈神经网络(FFNN)、深度神经网络(DNN)和循环神经网络(RNN)。通过简单的示例和代码,帮助前端开发者快速入门并理解神经网络的基本概念。文章还对比了各类神经网络的特点和适用场景,并简要介绍了卷积神经网络(CNN)的替代方案。
130 1
|
1月前
|
Web App开发 JavaScript 前端开发
探索Deno:新一代JavaScript/TypeScript运行时环境
【10月更文挑战第25天】Deno 是一个新兴的 JavaScript/TypeScript 运行时环境,由 Node.js 创始人 Ryan Dahl 发起。本文介绍了 Deno 的核心特性,如安全性、现代化、性能和 TypeScript 支持,以及开发技巧和实用工具。Deno 通过解决 Node.js 的设计问题,提供了更好的开发体验,未来有望进一步集成 WebAssembly,拓展其生态系统。
|
1月前
|
JavaScript 前端开发 API
Vue.js响应式原理深度解析:从Vue 2到Vue 3的演进
Vue.js响应式原理深度解析:从Vue 2到Vue 3的演进
57 0
|
1月前
|
JavaScript 安全 前端开发
探索Deno 1.x:安全JavaScript/TypeScript运行时的新篇章
【10月更文挑战第21天】Deno 1.x 是由Node.js创始人Ryan Dahl发起的项目,旨在解决Node.js的安全和模块化问题。Deno 1.x 版本带来了统一的运行时、默认安全、ES模块支持和内置TypeScript支持等新特性。其安全模型基于最小权限原则、沙箱环境和严格的远程代码执行控制,适用于Web服务器、命令行工具、桌面和移动应用及微服务开发。本文探讨了Deno 1.x的核心特性、安全模型及其在现代Web开发中的应用。