1.浏览器工作原理和V8引擎
发布于 2022年 02月 17日 05:38
前端需要掌握的技术:HTML、CSS、JavaScript
番前篇
JavaScript优势
Any application that can be written in JavaScript, will eventually be written in JavaScript. —Jeff Atwood (源自于StackOverflow作者杰夫·阿特伍德:任何可以使用JavaScript来是实现的应用最终都会使用JavaScript实现)
JavaScript应用场景
- Web开发
- 原生JavaScript开发
- jQuery开发
- Vue、React、Angular框架开发
- 移动端开发
- ReactNative
- Weex
- 小程序开发
- 支付宝小程序
- 微信小程序
- uniapp
- Taro
- 桌面端应用开发
- Electron
- 后端开发:
- 原生Node开发
- 基于原生的Express框架
- 基于原生的Koa框架
JavaScript让人迷惑的知识点
- 作用域
- 作用域理解、作用域提升、会计作用域、作用域链
- AO/GO/VO ...
- 函数、闭包
- 闭包访问规则、闭包的内存泄露、函数this指向
- 面向对象
- JavaScript面向对象、继承、原型、原型链
- ES新特性
- Promise、asyn&await、ES7/8/9/10相关
- 其他相关
- 事件循环机制、微任务、宏任务、防抖、节流、内存管理
JavaScript是一门编程语言
JavaScript是一门高级的编程语言
从编程语言发展历史来看,主要分为三个阶段:
- 机器语言:以二进制为指令的10010010
- 汇编语言:mov ax,bx等相关汇编指令
- 高级语言:C、C++、Java、JavaScript、Python
从编程语言发展历史来看,最终能被计算机识别的只有机器语言,所以无论是高级语言还是汇编语言最终都会被解释称为机器指令(语言)在计算机上执行。同时,高级语言相对于机器语言和汇编语言来说又相对容易符合常人的思维方式被人们所接受.
浏览器工作原理
从输入URL到页面渲染过程中发生了什么?
- 在浏览器地址栏输入www.baidu.com
- 浏览器会进行DNS解析,会对距离你最近的服务器进行请求
- 通过TCP/ICP三次握手,百度服务器会返回index.html
- script遇到响应的资源服会发送请求务器会返回相应的资源
浏览器通过请求得到响应的资源,最终解析这些脚本文件还是浏览器内核
浏览器内部渲染
常见的浏览器内核:
- Gecko:早期Netsscape和Mozilla Firefox浏览器使用
- Trident:微软开发,主要在IE浏览器使用
- WebKit:基于KHTML开发,主要在Safari上使用
- Blink:是Webkit的一个分支,主要在Chrome、Edge、Opera上使用
Blink内核工作流程图:
浏览器内核渲染文件的过程:
浏览器从上到下执行解析index.html页面,标准的规范是style相关资源放在header下面,接着是html相关内容,最后执行的是JavaScript脚本文件。
执行HTML代码的过程中遇到JavaScript代码会立即停止,直到JavaScript代码片段执行结束才会接着往后执行
如果我们不按照这种规范执行那么会产生什么后果呢?假设在一种网络不好的环境下面,进入页面先加载JavaScript文件,文件中写了定时器,异步等相关从影响页面加载的JavaScript代码,特别影响用户体验,如果HTML优先于CSS代码执行,作为一个网站开发者是不愿意让用户看到一个DIV元素从空白到最大这样一个执行过程的.
上面简单介绍了JavaScript代码加载的过程,JavaScript代码被执行被计算机所识别则是需要JavaScript引擎来操作。
JavaScript引擎是帮助我们将JavaScript代码翻译成CPU来执行,简单来说:就是将
var a = '123'
转化为10110100
指令。
常见的JavaScript引擎:
- SpiderMonkey:第一款JavaScript引擎
- Chakra:微软开发,用于IE浏览器
- JavaScriptCore:Webkit中的JavaScript引擎,小程序中也是使用此引擎解析JS代码
- V8:Google开发的强大的JavaScript引擎,也用于Node代码解析
浏览器内核和JavaScript引擎的关系:
以WebKit为例,WebKit事实上有两部分构成:
- WebCore:负责解析、布局、渲染HTML相关工作
- JavaScriptCore:解析、执行JavaScript代码
类似于小程序框架的图解为:
Node&Chrome->V8引擎
主要用于Chrome和Node.js,使用C++编写的Google高性能的JavaScript和WebAssembly引擎。
V8引擎底层原理图:
以代码
const a = '123'
为例子,
V8引擎首先会对这段代码做两件事:词法分析 和 语法分析
//词法分析生成tokens对象,结构如下:
tokens: [{type: 'keyword', value: 'const'}, {type: 'indetifier',value:'a'}]
//接着进行语法分析 生成语法分析树AST Tree
Program{
...
type: 'Program',
body:{
VariableDeclaration{
init: Literal{
raw: '123'
}
}
}
...
sourceType:"module"
}
类似于虚拟DOM
和babel
中的语句转换都是进行了语法解析相关抽象语法树,Ignition库通过转换成的抽象语法树转换成bytecode字节码
,之所以转换为字节码的而不是机器码原因是因为V8引擎需要负责将代码在(Windows,MacOS,Linux)
多平台运行,而不同的CPU则使用了不同的CPU架构,能执行的机器指令则不相同,而字节码就可以是跨平台的,可以在任意CPU架构执行。最终由字节码转换为汇编指令,最终转换为0101
的二进制指令。
TurboFan负责收集执行信息,如果频率较高标记为HOT
,MainchineCode负责优化的机器码。
Parse
模块主要将JavaScript
代码转换成AST抽象语法树
Ignition
是一个解释器,主要将AST抽象语法树
转换成ByteCode字节码
TurboFan
是一个编译器,主要将ByteCode字节码
编译成为CPU可以直接执行的机器码PreParser
对JavaScript代码
进行预解析
//Lazy Parsing 延迟解析
function Outer(){
function Inner(){
console.log('Inner');
}
}
Outer()
类似于Inner
函数可能永远不会发生执行的情况下,又想了解其内部发生了什么V8引擎就会对其进行预解析,只有发生执行才会进行Parse
的全量解析,这样就保证了V8引擎的工作效率