首页 > 编程语言 >JavaScript的工作原理:引擎、运行时和调用堆栈

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

时间:2023-10-12 21:38:19浏览次数:52  
标签:调用 浏览器 代码 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://www.sessionstack.com/solutions/developers/?utm_source=medium&utm_medium=blog&utm_content=Post-1-overview-getStarted

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

 

标签:调用,浏览器,代码,JavaScript,引擎,堆栈
From: https://www.cnblogs.com/qfy0411/p/13973456.html

相关文章

  • 关于 C# / .Net / IIS Web Service 调用 exe
    转自:https://blog.csdn.net/sby5104/article/details/110189048最近一个面试,面试官说他们现在的架构是通过IIS部署的WebService调用Server端的WindowsApplication也就是exe。面试拉跨之后自己尝试了一下这种实现方式,在这里记录一下自己遇到的坑,然后留一下查到的解决方案。......
  • 记录--h5调用手机摄像头踩坑
    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助1.背景一般业务也很少接触摄像头,有也是现成的工具库扫个二维码。难得用一次,记录下踩坑。2.调用摄像头的方法2.1. input<!--调用相机--><inputtype="file"accept="image/*"capture="camera"><!--调用......
  • 【前端小技巧】如何使用 Eolink Apilkit 调用 Mock ?
    在开发过程中,进度比较赶的情况下,前端人员当页面写完时,后台的接口还没写完,等要交付的时候后端才把接口给你,这个时候就很尴尬。这个时候Mock就可以很好的解决这个问题,前端团队可以在API还没开发完成的情况下,借助MockAPI实现预对接,加速开发进程。测试团队可以通过MockAPI解......
  • Android 通过bin二进制程序调用jar原理
    最近在研究monkey测试,发现monkey测试的代码都是JAVA编写的,通过编译生成jar包,而我们在执行测试时直接执行/system/bin/monkey这个二进制程序的,那么它是如何能调起java程序的呢?先来看看monkey二进程程序的生成.development\cmds\monkey\Android.mkLOCAL_PATH:=$(callmy-dir)i......
  • simulink中调用python脚本
      command='test.py&';%后轴&:等待调用结束(command='test.py';%无后轴&:立即执行下一句[status,cmdout]=system(command,'-echo');    参考:详解MATLAB的函数system()和shell转义字符“感叹号”,并利用它们实现在MATLAB中运行(调用)外部exe程序_matlabsy......
  • 【前端小技巧】如何使用 Eolink Apilkit 调用 Mock ?
    在开发过程中,进度比较赶的情况下,前端人员当页面写完时,后台的接口还没写完,等要交付的时候后端才把接口给你,这个时候就很尴尬。这个时候Mock就可以很好的解决这个问题,前端团队可以在API还没开发完成的情况下,借助MockAPI实现预对接,加速开发进程。测试团队可以通过MockAPI......
  • JS 堆栈跟踪
    堆栈跟踪APIV8中抛出的所有内部错误在创建时都会捕获堆栈跟踪。可以通过非标准error.stack属性从JavaScript访问此堆栈跟踪。V8还具有各种钩子,用于控制堆栈跟踪的收集和格式化方式,以及允许自定义错误也收集堆栈跟踪。本文档概述了V8的JavaScript堆栈跟踪API。functio......
  • static 特点2 多了一种调用方式 不需要实例化,可以直接类名调用
    效果1  实例化后被调用 效果2 ......
  • 调用微信接口返回openid
    privateStringgetOpenId(Stringcode){Stringurl="https://api.weixin.qq.com/sns/jscode2session";HashMapmap=newHashMap();map.put("appid",appId);map.put("secret",appSecret);m......
  • 在JavaScript中,最高效的方法来深度克隆一个对象是什么?
    内容来自DOChttps://q.houxu6.top/?s=在JavaScript中,最高效的方法来深度克隆一个对象是什么?将JavaScript对象进行深度克隆的最有效方法是什么?我见过使用obj=eval(uneval(o));,但这是非标准的做法,仅被Firefox支持。我曾尝试过obj=JSON.parse(JSON.stringify(o));,但对效率......