浏览器工作原理
JavaScript是一门编程语言
编程语言发展历史:
机器语言: 1000100111011000 ,一些机器指令;
汇编语言: mov ax,bx,一些汇编指令;
高级语言: C、C++、Java、 JavaScript、 Python;
计算机它本身是不认识这些高级语言的,所以我们的代码最终还是需要被转换成机器指令。
浏览器工作原理
认识浏览器的内核(浏览器的排版引擎)
不同的浏览器由不同的内核组成
Gecko :早期被Netscape和Mozilla Firefox浏览器浏览器使用; Trident :微软开发,被IE4~E11浏览器使用,但是Edge浏览器已经转向Blink ; Webkit :苹果基于KHTML开发、开源的,用于Safari ,Google Chrome之前也在使用; Blink :是Webkit的一个分支, Google开发,目前应用于Google Chrome、Edge、 Opera等;
排版引擎( layout engine ) ,也称为浏览器引擎( browser engine )、页面渲染引擎( rendering engine )或样版引擎。
浏览器渲染过程
HTML解析的时候遇到了JavaScript标签,会停止解析HTML ,而去加载和执行JavaScript代码
JavaScript代码由JavaScript引擎来执行
JavaScript引擎
认识JavaScript引擎
💡- 为什么需要JavaScript引擎呢?
高级的编程语言都是需要转成最终的机器指令来执行的 事实上我们编写的JavaScript无论交给浏览器或者Node执行,最后都是需要被CPU执行的 但是CPU只认识自己的指令集,实际上是机器语言,才能被CPU所执行 所以我们需要JavaScript引擎帮助我们将JavaScript代码翻译成CPU指令来执行
💡- 比较常见的JavaScript引擎有哪些呢?
- SpiderMonkey :第一款JavaScript引擎 ,由Brendan Eich开发(也就是JavaScript作者)
- Chakra :微软开发,用于IE浏览器;
- JavaScriptCore :WebKit中的JavaScript引擎,Apple公司开发;
- V8 :Google开发的强大JavaScript引擎,也帮助Chrome从众多浏览器中脱颖而出……
浏览器内核和JS引擎的关系
💡WebKit由两部分组成:
- WebCore :负责HTML解析、布局、渲染等等相关的工作;
- JavaScriptCore :解析、执行JavaScript代码;
在小程序中编写的JavaScript代码就是被JSCore执行的
V8引擎的原理
定义:
V8是用C ++编写的Google开源高性能JavaScript和WebAssembly引擎,它用于Chrome和Node.js等。 它实现ECMAScript和WebAssembly ,并在Windows 7或更高版本,macOS 10.12+和使用x64 , IA-32,ARM或MIPS处理器的Linux系统上运行。 V8可以独立运行,也可以嵌入到任何C ++应用程序中。
v8引擎架构图:
Parse(解析) : 词法分析(tokens)和语法分析
Parse模块会将JavaScript代码转换成AST (抽象语法树) , 这是因为解释器并不直接认识JavaScript代码
如果函数没有被调用,那么是不会被转换成AST的(会进行PreParser预解析)
转成AST:AST explorer
💡Ignition(解释器):将AST转换成ByteCode (字节码)
字节码 (好处 :跨平台 )→ 汇编代码 → 机器指令 (只出现一次)
Ignition → TurboFan 收集优化所需信息,例如标记热函数(出现频率高),提高性能
💡TurboFan(编译器) :可以将字节码编译为CPU可以直接执行的机器码
如果一个函数被多次调用,那么就会被标记为热点函数,那么就会经过TurboFan转换成优化的机器码,提高代码的执行性能;
但是,机器码实际上也会被还原为ByteCode ,这是因为如果后续执行函数的过程中,类型发生了变化(比如sum函数原来执行的是number类型,后来执行变成了string类型), 之前优化的机器码并不能正确的处理运算,就会逆向的转换成字节码
Deoptimization 反向优化 ⇒ ts(类型约束)运行性能相对较高
JavaScript内存管理
认识内存管理
不管什么样的编程语言,在代码的执行过程中都是需要给它分配内存的,不同的是某些编程语言需要我们自己手动的管理内存,某些编程语言会可以自动帮助我们管理内存
💡不管以什么样的方式来管理内存,内存的管理都会有如下的生命周期:
- 第一步:分配申请你需要的内存(申请);
- 第二步:使用分配的内存(存放一些东西,比如对象等);
- 第三步:不需要使用时,对其进行释放;
不同的编程语言对于第一步和第三步会有不同的实现:
- 手动管理内存:比如C、C++,包括早期的OC,都是需要手动来管理内存的申请和释放的(malloc和free函数);
- 自动管理内存:比如Java、JavaScript、Python、Swift、Dart等,它们有自动帮助我们管理内存;
JS的内存管理
- JS对于基本数据类型内存的分配会在执行时,直接在栈空间进行分配;
- JS对于复杂数据类型内存的分配会在堆内存中开辟一块空间,并且将这块空间的指针返回值变量引用;
JS的垃圾回收(Garbage Collection,GC)
对于那些不再使用的对象,我们都称之为是垃圾,它需要被回收,以释放更多的内存空间;
而我们的语言运行环境,比如Java的运行环境JVM,JavaScript的运行环境js引擎都会内存 垃圾回收器;
常见的GC算法(引用计数、标记清除)
💡引用计数:
- 当一个对象有一个引用指向它时,那么这个对象的引用就+1,当一个对象的引用为0时,这个对象就可以被销毁掉;
- 这个算法有一个很大的弊端就是会产生循环引用;
标记清除:
- 这个算法是设置一个根对象(root object),垃圾回收器会定期从这个根开始,找所有从根开始有引用到的对象,对于那些没有引用到的对象,就认为是不可用的对象;