从V8来谈谈JavaScript代码的执行

Node.js 中如何进行性能调优和内存分析 (如使用 V8 Inspector、heapdump)? 各位观众老爷们,大家好!今天咱们不聊风花雪月,只谈谈Node.js的性能调优和内存分析,保证让你的Node.js应用跑得像脱缰的野马,而不是老牛拉破车。希望今天的讲座能帮助你更好地理解 Node.js 的性能瓶颈和内存问题,并掌握一些常用的工具和技巧来优化你的 Node.js 应用。通过分析 Heapdump,你可以找到哪些对象占用了大量的内存,以及这些对象是如何被引用的。在 Chrome 开发者工具的 Memory 面板中,点击 "Load" 按钮,加载你生成的 Heapdump 文件。 阅读详情

我们知道,V8引擎是Google开发的开源JavaScript引擎,目前用在Chrome浏览器和Node.js中,核心功能是将JavaScript解析成机器能理解的机器码,供机器执行。

什么是V8

我们可以把V8看成一个虚拟机,其通过模拟实际计算机的各种功能来实现代码的执行,如模拟计算机的CPU,堆栈,寄存器等,此外,虚拟机还有自己的一套指令系统

有这样的虚拟机带来的好处是,只要我们按照虚拟机的规范去编写代码,那么即使我们在不同的操作系统,相同的代码执行出来的结果也能是相同的。可能Java虚拟机大家也都听过,听后端同学说面试的时候也常被问到,同样的也是通过将高级语言编译,只要在电脑上有Java虚拟机,我们就可以去编译执行Java语言,js也是同样的,但因为浏览器有自带的引擎来执行我们的代码,所以不像Java一样我们需要去安装,大家也就比较少感觉到它的存在了。

为什么要使用V8

知道了V8是什么之后,我们想想,为什么要使用V8,或者说为什么需要去解析我们写的代码

有计算机基础的同学应该知道,机器只能识别01的二进制代码,但是我们做为人,要我们去编写二进制代码来实现程序,显然是不太可能的,出于这个考虑,在一开始出现了汇编语言,相对于现在我们使用的高级语言诸如Java,C,JavaScript,python这些,汇编语言的编写还是相对麻烦的,但它还是需要解析执行,汇编语言都需要解析执行,何况高级语言呢。

V8是如何解析代码的

在谈到如何解析代码之前,我们要先知道两种主要的解析方式

主要的解析方式

动态解释执行

解释执行是解析方式的一种,需要先将输入的代码通过解析器编译成中间代码,然后通过解释器执行中间代码,然后直接输出结果。

使用解释执行的好处
  • 维护更灵活,我们只要保留源代码,修改源代码,执行的时候交给虚拟机即可
  • 只要存在解释器,源代码可以在任何操作系统上运行,可移植性好

静态编译执行

编译执行首先将源代码转换为中间代码,然后编译器再将中间代码转成机器代码。需要执行这段程序的时候,只要执行这段机器代码就可以了。通过这种方式,我们可以将虚拟机编译的机器代码直接存储起来,在需要的时候直接执行。

使用编译执行的好处
  • 因为直接编译生成了机器代码,所以执行的时候更快
  • 目标代码不需要编译器就能运行,在同类操作系统上使用灵活

这两种解析方式各有好处,虽然看上去过程很简单,但实际的解析,编译,解释还是很复杂的,每种语言的编译都会有所不同,会用到各自的虚拟机。

即便是一门语言,就如JavaScript,也有好几种流行的虚拟机,它们之间的实现也存在一定的差异,比如苹果公司在Safari中就是用JavaScriptCore虚拟机,Firefox使用了TraceMonkey虚拟机,而Chrome则使用了V8虚拟机。


那么回到我们的主题,V8是怎么解析代码的呢。是解释执行还是编译执行?都不是

V8并没有采用这两种方式中的一种,或者说,它结合了这两种方式。我们将这种混合使用解释执行和编译执行的方式称为JIT(Just In Time),实际上,JIT也有更细致的分类,但这里就不展开谈了。

看看V8执行JavaScript的完整流程
在这里插入图片描述

初始化运行环境

在V8开始解析代码之前,先要初始化运行JavaScript的环境,我们可以看到上面的图片左侧,列出了一些V8初始化环境时准备的东西:堆和栈空间、全局执行上下文、全局作用域、事件循环系统等,这些内容都是我们运行JavaScript时所必须的

  • 堆栈是V8用来管理内存的管理模式
  • 全局执行上下文中包含了全局执行的一些内置函数,全局变量等信息
  • 全局作用域包含了一些全局变量
  • 另外,要我们的V8系统活起来,还需要初始化消息循环系统,消息循环系统包含了消息驱动器和消息队列,它如同V8的心脏,不断接受消息并决策如何处理消息。

理解这里初始化的运行环境,可以让我们更好地理解JavaScript里面各种代码是如何被执行的

宿主环境

宿主环境是我们理解运行环境之前要理解的一个环境,对于V8来说,一般可以做为宿主环境的有浏览器环境和Node环境,之所以是宿主,可以理解为,JavaScript只能在宿主环境下才能被运行,同时,JavaScript会影响到“宿主”的状态。

举最经常发生的例子,当我们在浏览器中,JavaScript的代码运行的时间过长,就可能会影响到浏览器的渲染机制,有时甚至会导致浏览器未响应,这就是JavaScript对宿主环境的影响。

构造数据存储空间:堆栈空间

JavaScript运行在宿主环境上,V8会由这些宿主环境去启动,然后宿主环境就回去初始化V8,同时初始化堆栈空间。

其实很简单,我们要运行这门语言,当然要先为这门语言去构建它的存储空间,但问题是,为什么要用堆栈两种空间,两种空间各用来存储什么。这就涉及到了两种存储空间的利弊了。

栈

首先,我们说说栈。栈的特点是空间连续,且先进后出。至于它在JavaScript里的作用,可能你会经常听到函数调用栈这个名词,其实它在JavaScript中主要就是用来管理函数调用的,同时,和函数调用执行上下文相关的内容,如原始数据类型、用到的对象的地址、函数的执行状态、this的值都会存储在栈上。

而正因为栈的特点是空间连续,所以我们在初始化环境时,要在内存里面划分一块连续区域用于存储数据,但问题是,我们不能去划分一个过大的连续区域。先不说内存里面本身就很难得到一块大的连续区域,如果划分过大的栈空间用于存储的话,那对内存本身也是一种浪费,所以V8对栈空间大小做了限制,这也就是我们平时说的,栈空间溢出的原因。

堆

通过V8来对栈空间大小做出限制,解决了分配空间问题和内存浪费的问题,但是,如果我们遇到了比较大的数据的话,那分配空间又成了问题,因此V8引入了堆空间来存储较大的数据。

堆空间是一种树形的存储结构,用来存储对象类型的离散的数据,和栈空间不同,存放在堆空间中的数据是不要求连续存放的,从堆上分配内存块没有固定模式的。在JavaScript中,除了原始数据类型,其他的基本都是对象,上面也说了,栈空间里面会存储用到的对象的地址,而这个地址就指向了堆空间的某一个对象的地址。

堆栈空间创建完后,后面的数据就都会存储在这两个空间中了。

全局执行上下文和全局作用域

有了存储空间,V8就可以开始初始化全局执行上下文和全局作用域了。

当 V8开始执行一段可执行代码时,会生成一个执行上下文。V8用执行上下文来维护执行当前代码所需要的变量声明、this指向等。

当V8开始执行代码的时候,就会生成执行上下文,因为一开始都是先有的全局执行上下文,所以在这里初始化了全局执行上下文。全局执行上下文包括词法环境,变量环境和this关键字。

  • 词法环境:包含了使用let、const等变量的内容
  • 变量环境:在这里初始化的,包括创建全局中像浏览器的window对象,setTimeout,setInterval等API。
  • this关键字:指向当前的执行上下文

全局执行上下文在V8执行过程中是不会被销毁的,它会保存在堆中。

而执行上下文的区别,和全局作用域的区别,可能在ES6中,多了块级作用域后我们更能去区分,在一个执行上下文中,是可以有多个作用域的,就像下面在全局执行的代码

var g = 'global'
{
    let b = 'block'
}

这里全局执行上下文包括了两个作用域,一个是全局作用域,一个是块级作用域,但它们都是在全局执行上下文中的。

另一个区别,执行上下文是在我们调用函数时,动态创建的,除了全局执行上下文需要在我们初始化环境时就创建,而作用域是在我们解析JavaScript的时候,就确定下来的。

具体的作用域和执行上下文我们会在下面解析JavaScript的时候详谈,这里我们只是说说全局执行上下文和全局作用域。

构建事件循环系统

在构建完存储空间和执行上下文之后,因为V8是使用宿主环境的线程来运行JavaScript代码的,像在浏览器上就会去使用浏览器的主线程,但是如果我们执行完一段代码,就退出线程,那意味着下次再有代码要执行时,要重新初始化环境,这显然是不合理的。

所以V8为此构建了一个事件循环系统,在代码中添加一个循环语句,在循环语句中监听下个事件,比如你要执行另外一个语句,那么激活该循环就可以执行了

浏览器的主线程除了执行JavaScript之外,还要执行别的内容,所以V8实现了这个事件循环系统后,每当有新的任务,就会推到主线程的任务队列,当前面的任务执行完,就会执行这个推入的任务。

因此我们在写JavaScript时,要注意一个函数执行的时间不能过长,如果过长的话可能会阻塞其他事件的执行或者页面的交互性能。可以考虑放到web worker执行或者使用时间切片处理。

解析执行JavaScript代码

在谈及解析之前,我们要明白,我们写的代码,说到底只是一段字符串内容,要让一个引擎去对一段字符串内容进行识别解析执行,不太实际,所以我们需要先对它进行一定的解析,转换成另一种结构,然后根据这种结构来转化代码执行。

上面的图中我们也可以看到了,代码通过解析,生成了AST抽象语法树和作用域。AST便是V8易于转换执行的结构。

作用域

我们先看看这里解析生成的作用域,为什么要在这里解析作用域,在这里解析的作用域有什么用,对我们的代码有什么影响,理解了这些问题,会让你对JavaScript的作用域链有更深的理解

我们可以看看下面的这段代码

var name = '全局'
var scope = 'global'

function foo(){
        var name = 'foo'
        console.log(name)
        console.log(type)
}

function bar(){
        var name = 'bar'
        var type = 'function'
        foo()
}
bar()

这段代码最终会打印出什么呢,可以想一想,即使你知道正确答案,你又知道为什么吗,我们先继续聊聊刚才的问题

首先,作用域是什么,简单来说,作用域就是用来存储变量和函数的地方,而我们常见的,在ES6之前,有全局作用域和函数作用域,一开始我们在V8初始化环境的时候,就会创建全局作用域,而当我们运行某个函数,就会创建相应的函数作用域,而当出现函数作用域时,就会出现作用域链。

全局作用域和函数作用域

全局作用域:上面已经提到了,时在V8初始化环境的时候就会创建的,所以我们的代码可以去直接调用到全局的一些变量,比如浏览器中的window和document,再比如node中的Global,File等。此外,全局作用域在运行过程中不会被销毁,除非V8退出。

函数作用域:在函数执行的时候的编译阶段创建的,当函数执行完毕,就会退出当前的函数作用域,而且这个函数作用域也随着退出而被销毁。

作用域链

知道了全局作用域和函数作用域之后,我们就可以来理解作用域链了。上面提到了,当出现函数作用域时,就会出现作用域链,因为既然V8引擎已经启动了,说明全局作用域已经存在了,而函数要么是在全局作用域中声明,要么是在函数作用域中声明,所以至少会有两个作用域,也就形成了一个作用域链。

嗯?上面我说的是在执行的时候函数作用域会被创建,为什么这里我用了声明这个词呢,要知道执行所在的作用域和声明的作用域可能不在同一个地方,执行的时候创建函数作用域,那作用域链不是应该按执行的时候所在的作用域来构成吗?这种“理所当然”的理解正是很多人答错上面那段代码输出结果的原因。

那么正确答案是什么

首先要知道一个概念性的东西,作用域分两种,一种是词法作用域,一种是动态作用域,而JavaScript使用的是词法作用域。在《你不知道的JavaScript 上》里面有写到

简单地说,词法作用域就是定义在词法阶段的作用域。换句话说,词法作用域是由你在写代码时将变量和块作用域写在哪里来决定的,因此当词法分析器处理代码时会保持作用域不变(大部分情况下是这样的)

因此,上面得到的正确打印结果应该是
foo global
因为bar虽然是在foo函数里面被调用的,但它是在全局下声明的,所以它的作用域链是 global->bar而不是global->foo->bar。

因此,回到我们的问题,为什么要在解析的时候就把作用域创建好,我个人的理解是:因为大部分情况下,我们的函数作用域是由函数,或者是块级作用域,是由我们写的位置来决定的,所以我们在编译的时候就可以解析出相应的作用域链,在后面我们正式执行代码的时候,就可以直接使用这部分内容了,不用增加执行时的额外开销。这样也能加快我们代码的执行。

与执行上下文的关系

在上面谈到初始化环境时我们已经提到了,执行上下文是动态创建的,而作用域是在解析时静态确定的。对于函数调用栈来说,我们更应该看的时执行上下文。当我们在全局执行一个函数的时候,就会形成一个调用栈。虽然因为JavaScript使用的是词法作用域,所以在使用变量和调用方法时,会沿着作用域链去寻找相应的变量和方法,但是在内存中,调用栈的结构,栈里面的函数顺序,是由执行上下文来决定的,也就是看什么时候调用,越早调用的函数越早入栈,而栈底就是全局执行上下文。

AST

我们首先要看看AST是什么,可以通过这个网址https://astexplorer.net/来查看一些代码对应的AST结构

在这里插入图片描述

AST是一种树状的结构,如图我们也可以看到结构,我们在用babel来编译代码也是用到了AST

我们也可以通过一个npm包recast来更细致地学习AST

npm i recast -S

安装这个npm包之后可以根据里面的API来对AST树有细致的了解,因为这里主要讲的是V8,所以就不深入地去说AST了,我们现在只要知道在编译阶段V8会将其先编译为AST

解析成中间代码

那么根据图示
在这里插入图片描述
接下来我们要将AST解析成中间代码,但V8并不会一次性将所有的JavaScript解析为中间代码,这涉及到两个原因

首先,如果我们一次性解析所有的JavaScript,那么解析的时间无疑会受JavaScript代码大小的影响,如果JavaScript代码不多,那还好说,但是现如今的页面,一个页面就有好几个JavaScript文件,如果一次性都解析,那么毫无疑问,会让用户感到卡顿,这显然是不行的

其次,我们解析生成的字节码和编译之后的机器码都会存放在内存中,如果一次性解析所有的JavaScript,这些中间代码和机器码会一直存放在内存中,如果是在PC端还好,在移动端,手机本身内存就不多,内存占用的问题对用户的影响是很大的。

为了解决这些问题,所有主流的JavaScript虚拟机都实现了惰性解析。

惰性解析

所谓惰性解析,指的是解析器在解析过程中,如果遇到函数声明,那么会跳过函数内部的代码,不会为其生成AST和字节码,仅生成顶层代码的AST和字节码。

举个简单的例子

function fn(x,y){
    var z = 1000
    return x+y+z
}
var a = 1
var b = 10
fn(a,b)

当V8遇到这段代码的时候,V8会按代码的编写顺序,至上而下地去解析这段代码,在解析过程中,首先会遇到函数声明fn,那么按上面说的,会对函数声明做出惰性解析的处理,将函数变成一个对象,你可以理解为如下的对象

fn:{
    name:'fn',
    code:`
        function (x,y){
            var z = 1000
            return x+y+z
        }
    `
}

接着继续解析,由于后面都是顶层代码,所以V8会为它们生成AST,然后根据该AST生成中间代码,再至上而下执行代码,当执行到fn(a,b)时,就会去找到上面的那个对象,然后找到其code属性的字符串,使用原来的方式去解析这段字符串,同样编译生成AST和中间代码,然后再解释执行。通过这种方式,我们只有在真正执行到这个函数时,才会去解析这段函数,解析后再执行。

但是为了解决闭包问题,V8引用了预解析器,遇到函数声明时,除了生成转换对象外,还会进行简单的解析,判断内部是否有语法错误和是否有引用外部函数变量,如果引用了外部函数变量,则把这个函数变量复制到堆空间中。

字节码

字节码,就是上面图片中根据AST编译生成的中间代码。在V8中,字节码有两个作用,我们也从上面的图片中看到了

  1. 直接做为中间代码被解释器执行
  2. 由编译器将其转换为二进制机器码,再执行

然而,AST实际上也可以直接解析成二进制机器码,那你可能会有疑惑,为什么还要多一步中间的字节码,实际上,早期的V8并没有使用字节码,而是直接解析成二进制机器码

早期没用字节码的V8

早期的V8执行流程如下图
在这里插入图片描述
在早期的V8执行代码流程中,采用了两个编译器

  • 基线编译器,它负责将JavaScript代码编译为没有优化过的机器代码。
  • 优化编译器,它负责将一些热点代码(执行频繁的代码)优化为执行效率更高的机器代码。
  1. 在早期V8中,会先将JavaScript代码解析生成AST
  2. 然后将AST编译生成没有优化的二进制代码,并解释执行
  3. 在这个过程中,发现了执行频率比较高的代码,对它们做了标记,使用优化编译器将其编译成优化的二进制代码,执行该优化的代码
  4. 如果优化的代码不能满足现状,就通过反优化变回未优化二进制代码

早期的V8会将JavaScript编译成未经优化的二进制机器代码,然后再执行这些未优化的二进制代码,通常情况下,编译占用了很大一部分时间,为了减少编译的时间,早期的V8采用了机器代码缓存

这种方式其实就是我们算法上常说的空间换时间,因为空间常常比时间廉价。V8通过两种策略来实现机器代码缓存

  1. 首先,在首次执行JavaScript代码的时候,会编译生成二进制代码,然后将二进制代码缓存到内存中
  2. 除了缓存到内存外,V8还会将二进制代码缓存到硬盘上,这样即使我们关闭浏览器,重新打开的时候也能从硬盘上拿到缓存的代码来执行

这种直接编译成二进制代码的形式,其实比引入字节码性能更高,但是为什么后来的V8引入了字节码呢

拥抱字节码

上面提到了,早期的V8没有采用字节码,那是什么原因,让V8拥抱了字节码呢。

首先要回到上面的V8解决重复编译的问题,早期的V8采用了缓存策略来解决,但存在的问题是,JavaScript代码转换成二进制代码,占用的内存过大,看看下图
在这里插入图片描述
5k的JavaScript代码就会生成10M大小的二进制代码,那如果将多个JavaScript文件都编译为二进制代码存储在内存、硬盘中,那对内存来说可真是个噩梦。而引入字节码,就是为了解决这个策略对内存占用过多的问题,其实字节码能解决这个问题的原因也很简单,字节码占用内存少
在这里插入图片描述
如上图,虽然编译成字节码相比原JavaScript代码来说,大小还是多了几倍,但是相对于二进制代码来说,已经非常小了,是可以接受的内存占用。虽然采用字节码,会导致执行时性能略有降低,但是在代码的启动速度反而更快了,也就是说,采用字节码带来的代价,仅仅是减慢了执行时的一点时间而已。所以权衡利弊,V8最终拥抱了字节码。

Vue 技术栈 教你玩"坏" v8引擎 吃透 js 内存回收机制 现在开始逐步深入Vue 技术栈,想了想,技术栈专栏的主要内容包括: 1、Vue源码分析 2、手把手教 保姆级 撸代码 3、无惧面试,学以致用,继承创新 4、谈谈前端发展与学习心得 5、手写源码技术栈,附上详细注释 6、从源码中学习设计模式,一举两得 7、编程思想的提升及代码质量的提高 8、通过分析源码学习架构,看看优秀的框架 9、项目实战开发 10、面试准备,完善个人简历 阅读详情

相关推荐

【PADS-开发指南】

馒头破戒大师

sinat_23896491的博客 3211

图解 Google V8 # 01:V8 是如何执行一段 JavaScript 代码的?

说明 图解 Google V8 学习笔记 什么是 V8? V8 是 JavaScript 虚拟机的一种,由 Google 开发的开源 JavaScript 引擎,目前用在 Chrome 浏览器和 Node.js 中,其核心功能是执行易于人类理解的 JavaScript 代码。 JavaScript 引擎种类: SpiderMonkey V8 JavaScriptCore … JavaScript 引擎将人类能够理解的编程语言 JavaScript,翻译成机器能够理解的机器语言。 JavaScript

学习前端这门手艺,栈底到栈顶依次是:浏览器架构、Web 网络、事件循环机制、JavaScript 核心、V8 的内存管理、浏览器的渲染流程、Web 安全、CSS、React、Vue、Node、构建工具链等 1720

UE5游戏逆向实战:用FModel提取.pak文件中的3D模型(附Dumper-7避坑指南)

本文详细介绍了如何使用FModel工具从UE5游戏的.pak文件中提取3D模型,并提供了Dumper-7的避坑指南。内容涵盖FModel工具链配置、UE5特有的unversioned properties问题解决方案、Dumper-7实战流程以及模型后处理技巧,帮助开发者高效获取游戏资产。

weixin_30872499的博客 422

V8 javascript 引擎

V8是一个由丹麦Google开发的开源java script引擎,用于Google Chrome中。[2]Lars Bak是这个项目的组长。[3] V8在执行之前将java script编译成了机器码的,而非字节码或是直译它,以此提升效能。更进一步,使用了如内联缓存(inline caching)等方法来提高性能。有了这些功能,java script程序与V8引擎的速度媲美二进制编译。[4] V8组译器是基于Strongtalk组译器。[5] V8是Goo

男神的专栏 1733

学习记录——SIMPACK生成轨道谱文件的方法

生成轨道谱文件的方法,可以用于实测轨道谱导入和自制轨道谱导入仿真

weixin_51965897的博客 7793

STM32HAL库学习笔记九——LCD显示

本文不会对驱动编写做特别详细的描述,以记录CubeMX的部署流程为主。

weixin_44762233的博客 6917

【JavaScript运行原理之V8引擎】V8引擎解析JavaScript代码原理

V8 是一个接收JavaScript代码,并编译代码,执行代码的一个C++程序,编译后的代码可以在多种操作系统,多种处理器上运行。V8的工作:编译执行js代码、处理调用栈、内存分配、垃圾回收。

酷奇的博客 1415

游戏战斗系统架构设计的演绎之路——从一坨意大利面条到一座精密钟表

摘要:游戏战斗系统架构设计的演进之路 本文系统梳理了游戏战斗系统从早期街机到现代3A大作的架构发展历程。70-80年代的街机游戏采用基础碰撞盒判定(如《街头霸王》);90年代实现动画融合与状态机架构(《最终幻想》《拳皇》);2000年后MMO引入服务器验证与同步技术(《魔兽世界》);3D时代融合物理引擎与智能AI(《GTA5》《只狼》);移动端则发展出轻量化架构与云端判定(《王者荣耀》)。现代战斗系统已实现模块化、数据驱动和热更新,未来趋势是AI裁判与云战斗系统。这一演进过程展现了技术与创意的完美结合,数百

本博客聚焦游戏开发技巧、创业实战心得及大学热门课程干货。这里既有技术深度,也有思维广度,无论你是开发者、创业者还是高校学子,都能在这里找到适合自己的成长之路! 800

JS系列(二) - V8引擎的运行原理

当我们编写JavaScript代码时,它实际上是一种高级语言,这种语言并不是机器语言。高级语言是设计给开发人员使用的,它包括了更多的抽象和可读性。但是,计算机的CPU只能理解特定的机器语言,它不理解JavaScript语言。这意味着,在计算机上执行JavaScript代码之前,必须将其转换为机器语言。这就是JavaScript引擎的作用:事实上我们编写的JavaScript无论你交给浏览器或者Node执行,最后都是需要被CPU执行的;

qq_44376306的博客 1709

OpenClaw与大语言模型(Claude/GPT/MiniMax)的集成架构与最优配置策略

摘要 本文探讨了OpenClaw框架与大语言模型(Claude/GPT/MiniMax)的集成架构与优化策略。大语言模型具有强大的自然语言处理能力,但集成面临API成本、响应延迟、上下文管理等挑战。OpenClaw采用分层架构设计,包括用户界面层、对话管理层、提示工程层、模型适配层和API调用层,支持多模型切换、智能对话管理和成本控制。系统通过模型适配层实现不同API的统一调用,并提供缓存、监控等优化机制。该集成方案能够充分发挥大语言模型的优势,为本地AI助理提供更智能的服务。

一键难忘的博客 1692

基于YOLOv11的工业装配完整性智能检测系统

在现代工业生产中,产品质量控制是确保企业竞争力的关键环节。其中,装配完整性检查——即检测产品是否安装了所有应有的部件,是质量检测中的重要一环。传统的人工检测方法存在效率低、易疲劳、主观性强等问题。本文提出了一种基于深度学习的目标检测算法YOLOv11的工业装配完整性智能检测系统,通过计算机视觉技术自动识别和验证产品装配的完整性。本文将详细阐述从数据准备、模型训练到系统部署的完整流程,提供可执行的代码实现,并介绍一个适用于该任务的参考数据集。

YOLO 551

什么是 V8 JavaScript 引擎

基本概念与作用说明V8 的工作原理主要特性完整且丰富的代码示例示例一:在 Node.js 中使用 V8 引擎示例二:性能测试示例三:内存管理示例四:调试信息示例五:异步执行不同角度的功能使用思路性能优化内存管理并发执行调试和性能分析实际工作开发中的使用技巧V8 JavaScript 引擎是Google开发的一款高性能JavaScript引擎,最初设计用于Chrome浏览器,但现在已经广泛应用于其他领域,如Node.js服务器环境。

一个做过前端开发的产品经理,经历过睿智产品的折磨导致脱发之后,励志要翻身"农奴"把歌唱,一边打入敌人内部一边持续提升自己,为我们广大开发同胞谋福祉,坚决抵制睿智产品折磨我们码农兄弟! 1582

AUTOSAR AP——SM模块

对AUTOSAR AP中状态管理模块SM,从模块定义、总结等多方面进行了介绍。

weixin_43627682的博客 284

请你谈谈:从宏任务&&微任务的角度谈谈js代码的执行顺序

当JavaScript引擎遇到异步代码时,它不会立即执行这些代码,而是会将异步操作(如定时器、网络请求、文件读写等)的回调函数或Promise等异步处理机制放入宿主环境(如浏览器或Node.js)的某个任务队列(如宏任务队列或微任务队列)中。异步操作的结果会在将来的某个时间点成为可用,此时宿主环境会将其对应的回调函数或Promise解决(resolve)或拒绝(reject)的处理程序放入JavaScript引擎的执行栈中执行。与宏任务不同,微任务是在当前宏任务执行完毕后,下一个宏任务开始之前执行的。

一个搬砖工人 897

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

V8、JSCore、Hermes、QuickJS,hybrid开发JS引擎怎么选

V8、JSCore、Hermes、QuickJS,hybrid开发JS引擎怎么选

idaretobe的专栏 3375

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

javascript代码用什么打开,js打开窗口的几种方式

JavaScript代码是怎么在浏览器里面运行的?下面简单探索一下。

2301_79533350的博客 357

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

JS | 深入谈谈 JavaScript 的垃圾回收机制

垃圾回收机制也称Garbage Collection简称GC。在JavaScript中拥有自动的垃圾回收机制,通过一些回收算法,找出不再使用引用的变量或属性,由JS引擎按照固定时间间隔周期性的释放其所占的内存空间。在C/C++中需要程序员手动完成垃圾回收。

青春木鱼的博客 2200

透过V8深入理解JavaScript的对象

我们知道,V8是Chrome用来编译执行JavaScript的JavaScript引擎,所以如果我们要了解JavaScript,那么结合V8能让我们更好地理解,这篇博客将结合V8,来谈谈JavaScript种的对象 对象 什么是JavaScript的对象 什么是JavaScript的对象, JavaScript中的对象,并不是单单指Object,JavaScript这门语言本身,是基于对象的,可以说,JavaScript里面的大部分内容,都是由对象构成的。比如函数,数组,这些都是由对象构成的,甚至一些基本类

zem 807

简述javascript的执行原理,javascript在什么地方执行

但是在执行函数的时候,和变量不太一样,变量涉及到作用域提升的问题,但是如果定义了一个函数,那么函数调用写在函数定义之前或者之后都能够执行。因为在解析阶段解析出这是一个函数,那么就会为这个函数创建一个存储函数对象,然后指向它,在需要调用的时候去执行函数体内部的代码。①V8为了运行代码,内部会有一个执行上下文栈(Execution Context Stack,简称ECStack函数调用栈),用于执行代码的调用栈,一般是在里面放函数的。函数的父级作用域和它的定义位置有关系,和调用位置是没有关系的。

神经网络爱好者 128

javascript代码在哪里运行,javascript怎么运行代码

先自我介绍一下,小编13年上师交大毕业,曾经在小公司待过,去过华为OPPO等大厂,18年进入阿里,直到现在。深知大多数初中级java工程师,想要升技能,往往是需要自己摸索成长或是报班学习,但对于培训机构动则近万元的学费,着实压力不小。Node.js是一个事件驱动I/O服务端JavaScript环境,基于Google的V8引擎,V8引擎执行Java的速度非常快,性能非常好。安装非常方便,一路点next就好,最好安装在c盘,其他盘在使用中可能会遇到麻烦,亲测!官网:https://nodejs.org/en/

wenangou的博客 788

也来谈谈JS的执行上下文与词法环境

JS 的执行上下文(execution context)和词法环境(Lexical environment)是很多前端er时不时听到,却不曾深入了解的知识点。似乎只具理论意义,也不会影响我们日常编程。事实上,**词法环境的原理与我们常常用到的很多知识点息息相关,比如变量提升,闭包(closure),作用域链(scope),箭头函数的原理等等**。这些看似散乱甚至很多同学需要背诵的知识点,其实根本上都是JS词法规则的外化与延伸。

辰辰沉沉大辰沉 1525

V8工作原理

文章预览:01 栈空间和堆空间:数据是如何存储的?02 垃圾回收:垃圾数据是如何自动回收的?2.1 调用栈中的技术是如何回收的2.2 堆中的数据是如何回收的2.2.1 新生代2.2.2 老生代03 编译器和解释器:V8是如何执行一段JavaScript代码的?3.1 编译器和解释器3.2 V8 执行一段代码的流程3.3 即时编译技术JIT3.4 JavaScript性能优化 01 栈空间和堆空间:数据是如何存储的? ​ JavaScript 是一种弱类型的、动态的语言。这意味着我们不需要告诉

qq_45644850的博客 732

「JavaScript深入」谈谈 JS 的垃圾回收机制

谈谈JS的垃圾回收机制:内存管理、可达性、内存回收机制、V8对于垃圾回收机制的优化

XH_jing的博客 1377

编写快速、高效的JavaScript代码

许多Javascript引擎都是为了快速运行大型的JavaScript程序而特别设计的,例如Google的V8引擎(Chrome浏览器,Node均使用该引擎)。在开发过程中,如果你关心你程序的内存和性能的话,你应该了解并意识到,在你的代码背后,浏览器的JavaScript引擎中到底发生了什么事情。 不论的V8,SpiderMonkey(Firefox)、Carakan(Opera)、Chak

Draco 2042

简明扼要地谈谈v8的隐藏类和Inline Cache(內联缓存)

还有一个是从AST直接生成机器码,但是这个现在已经被换成了Ignition(解释器)+TurboFan(类型优化编译器)的架构了。 先说隐藏类:对一个JS对象的属性访问而言,最简单的解释器实现会把属性建模为运行时的hash查询。然而这个性能太慢,怎么优化呢?简单的说就是参考静态编译器的思路,把属性field的按名字访问,抹掉名字信息,变成按offset访问。——不过这样就需要一个clas

cteng的专栏 2761

谈谈你对nodejs的理解?

概念 Node.js是一个基于Chrome V8引擎的javascipt的运行环境。 Node.js使用了一个事件驱动、非阻塞I/O的模型, Node.js轻量又高效,能够使我们在本地运行javascript Nodejs能做什么 1、提供数据给浏览器展示 2、保存用户提交过来的数据 3、数据统计与分析 服务器Node.js和浏览器js的区别是什么? 1.node.js是平台,Java...

高先生的猫 1364
上一篇: 手写webpack部分功能实现ES module语法的编译
下一篇: 透过V8深入理解JavaScript的对象
前端小黑
博客等级 码龄9年 148粉丝 222原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值