【JS】V8 引擎原理
文章目录
- 认识JS引擎
- V8引擎原理
- V8引擎架构
- V8引擎的解析图
认识JS引擎
- 为什么需要 JS 引擎?
1. `高级编程语言`都有转化成`最终的机械指令`来执行的
2. 我们平时编写的js,无论你交给`浏览器或Node`执行,最后都是需要被CPU执行的
3. 但CPU只认识自己的指令集,实际上是机械语言,才能被CPU所执行
4. 所以我们需要JS引擎将JS代码翻译成CPU指令来执行
- 常见的 JS 引擎有:
5. SpiderMonkey:第一款JS引擎,由Brendar Eick开发,也就是JS作者
6. Chakra:微软开发,用于IE浏览器
7. JavaScriptCore:WebKit中的JS引擎,Apple公司开发
8. V8:Google开发的强大JS引擎,帮助Chrome从众多浏览器中脱颖而出
9. 等等。。。。。
浏览器内核与JS引擎的关系
- 以WebKit为例,它由2部分组成
第一部分 WebCore:负责HTML解析、渲染布局等相关工作
第二部分 JavaScriptCore:解析执行JS代码
- 在小程序中编写的JS代码就是被JSCore执行的
V8引擎原理
- V8是用
C++
编写的Google开源高性能的JavaScript
和WebAssembly
引擎,用于Chrome和Node.js等 - 它实现
ECMAScript
和WebAssembly
,并在win7或更高版本,macOS10.12+版本和使用x64、IA-32、ARM或MIPS处理器的Linux系统上运行 - V8可以独立运行,也可以嵌入到任何
C++
程序当中
工作流程图:
流程图分析:
- parse:对js代码进行解析,包括词法分析和语法分析
const name = "lisi";
// 词法分析:拆分js代码(const, name, =, "lisi", ;,)
tokens = [{type:"keyword",value: const,}{type:"identifier",value: "name",}...
]
// 语法分析:再根据tokens进行分析,比如type是啥,value又是啥,分析完后生成 AST 树
AST 树如下图所示:
const name = "lisi";
对应的AST
树
const name = "lisi";
对应的JSON
结构
{"type": "Program","start": 0,"end": 20,"body": [{"type": "VariableDeclaration","start": 0,"end": 20,"declarations": [{"type": "VariableDeclarator","start": 6,"end": 19,"id": {"type": "Identifier","start": 6,"end": 10,"name": "name"},"init": {"type": "Literal","start": 13,"end": 19,"value": "lisi","raw": "\"lisi\""}}],"kind": "const"}],"sourceType": "module"
}
- 扩展:
babel
将ts
代码转换成js
代码过程
ts ==> ast树 ==> 修改ast树 ==> generate code (生成代码) ==> js
// 同理,es6转es5
ES6 ==> ast树 ==> ES5
- ignition:将
AST
树转换为bytecode
字节码
为什么不把 AST树 转换为 机械码0101 的形式?而要先转成字节码?
答:
代码的运行环境是不一定的,而不同的环境他有不同的CPU架构,
他们执行的机械指令是不一样的,而ignition他不知道该转换成什么机械指令的代码,
而bytecode字节码他相当于是跨平台的
v8引擎就会把`字节码`转换成对应的`汇编代码`然后再转换成相应平台(window、Linux)的CPU指令(0101)
- TurboFan:将ignition中执行次数比较多的代码,直接转换成对应的机械码(0101),提高性能
V8引擎架构
V8引擎本身的源码非常复杂,大概有超过100w行的C++代码,通过了解他的架构,可以知道他是怎么对JS执行的
Parse
- 该模块会将JS代码转换成AST(抽象语法树),因为解析器并不直接认识JS代码
- 如果函数没有调用,那么是不会转换成AST的
- Parse的V8官方文档:https://v8.dev/blog/scanner
Ignition
- 是一个
解析器
:会将AST树转换成ByteCode字节码 - 如果函数只调用一次,ignition会解析执行ByteCode字节码
- Ignition的V8官方文档:https://v8.dev/blog/ignition-interpreter
TurboFan
- 是一个
编译器
:可将ByteCode字节码编译成CPU可直接执行的机械码 - 如果一个函数被多次调用,那么就会被标记为
热点函数
,那么就会经过TurboFan转换成优化后的机械码,提高代码的执行性能 - 如果后续执行函数的过程中,类型发生了改变(比如sum函数原来执行的number类型,后面执行变成了string类型),之前优化的机械码就不能正常的处理运算了,就会逆向的转换成字节码
- TurboFan的V8官方文档:https://v8.dev/blog/turbofan-jit
V8引擎的解析图
官方:
Blink(内核):解析HTML,解析过程中遇到JS就会下载下来以引流的方式传递给V8引擎
Stream(数据流):获取源码并进行编码转换
Scanner(扫描器):做词法分析的,会转换成很多 tokens
Parser(解析):将tokens转换成AST树
PreParser(预解析):预解析后再将数据交给Parser
- 为什么需要预解析呢?
因为并不是所有JS代码从一开始就会被执行。如果直接全部解析所有代码,会影响网页的运行效率,所以V8引擎就实现了Lazy Parsing(延迟解析)方案。他的作用是将`不必要的函数进行预解析`,只解析暂时需要的内容(比如函数名),而对`函数的全量解析`是在`函数被调用的时候`才会进行比如我们在fun函数里面定义一个fn函数,那么fn函数就会进行预解析
function fun(){function fn(){ // 会被预解析var name = "lisi" // 不会被预解析}
}
【JS】V8 引擎原理相关推荐
- Google V8 引擎 原理详解
Google V8 引擎使用 C++ 代码编写,实现了 ECMAScript 规范的第五版,可以运行在所有的主流 操作系统中,甚至可以运行在移动终端 ( 基于 ARM 的处理器,如 HTC G7 等 ...
- 深入出不来nodejs源码-V8引擎初探
原本打算是把node源码看得差不多了再去深入V8的,但是这两者基本上没办法分开讲. 与express是基于node的封装不同,node是基于V8的一个应用,源码内容已经渗透到V8层面,因此这章简述一下 ...
- 浏览器工作原理和V8引擎
一.浏览器的工作原理 比如在浏览器中输入网址,然后dns进行解析,解析出的就是服务器的一个ip地址.服务器返回一个html文件,浏览器内核在解析html文件的过程中,遇到link标签和script标签 ...
- V8引擎-js执行原理
前言: 今天小编给大家讲解一下小伙伴们心中一直存在的问题,那就是我们在使用node环境或者浏览器的时候为什么可以执行js代码? 我们定义了很多的变量和函数内部是如何处理的? 以及我们常常说的作用域 ...
- 浏览器原理-v8引擎-js执行原理
浏览器原理-v8引擎-js执行原理 js简介 js应用: js的应用很广泛 可以应用于web,移动端,小程序,桌面应用,后端开发等 web开发包括(原生js,react,vue,angular等) 移 ...
- JavaScript 工作原理(二)-如何在 V8 引擎中书写最优代码的 5 条小技巧(译)
From:https://segmentfault.com/a/1190000014770145 原文请查阅这里,略有删减. 本系列持续更新中,Github 地址请查阅这里. 这是 JavaScrip ...
- JavaScript 工作原理之二-如何在 V8 引擎中书写最优代码的 5 条小技巧(译)
原文请查阅这里,略有删减. 本系列持续更新中,Github 地址请查阅这里. 这是 JavaScript 工作原理的第二章. 本章将会深入谷歌 V8 引擎的内部结构.我们也会为如何书写更好的 Java ...
- 干货:浏览器渲染引擎Webkit和V8引擎工作原理
浏览器的历史 W3C在80年代后期90年代初期发明了世界上第一个浏览器WorldWideWeb(后更名为Nexus),支持文本/简单的样式表/电影/声音和图片 1993年,网景(netscape)浏览 ...
- V8引擎解析JavaScript原理
为什么需要JavaScript引擎呢? 高级的编程语言都是需要转成最终的机器指令执行的 我们编写的JavaScript无论交给浏览器和Node执行,最后都是被CPU执行的 CPU只认识自己的指令集,实 ...
- 浏览器执行原理-V8引擎
浏览器内核 不同浏览器的内核组成 Gecko:早起被Netscape和Mozilla Firefox浏览器使用 Trident:微软开发,被IE4-IE11浏览器器使用,但在Edge已经转向Blink ...
最新文章
- openresty 前端开发入门五之Mysql篇
- 一处 ADO.NET Entity Framework 的逻辑BUG
- Depth-first Search深度优先搜索专题2
- 时间等待 c# 1614006220
- Python小笔记——urllib2得到重定向最终链接
- android 8.0后台定位,Android 8.0权限说明
- 手动为容器设置ip地址
- poj 2499第K短路模板
- Spring 在xml配置里配置事务
- [原创]CI持续集成系统环境---部署Jenkins完整记录
- lightoj 1029 最小生成树 + 最大生成树
- 可以载入史册的新名词:市场经济(蝳品经济)的上瘾依赖特性
- 北大学子求职经历与建议(IT类) 收藏
- 用python中的turtle库画蜡笔小新
- 算力之都杭州:楼市向何处去
- Docker镜像篇(2) - 玩转Dockerfile指令 - FRM、MAINTAINER、LABEL、COPY
- 编程思维---排他思想
- 怎么查看域名被墙_怎么查看域名是否被墙检测(教你一招域名被墙解决办法)...
- SpringCloud微服务,euraka、feign、hystrix组件学习
- Google需警惕苹果Apple TV的10大原因