前言: 今天小编给大家讲解一下小伙伴们心中一直存在的问题,那就是我们在使用node环境或者浏览器的时候为什么可以执行js代码? 我们定义了很多的变量和函数内部是如何处理的? 以及我们常常说的作用域以及变量提升到底是什么? 接下来小编将逐一的带大家去解决这些问题?
再说v8引擎之前,先带大家了解一下基本的知识~
Javascript是什么?
javascript是一门解释型的高级编程语言, 有高级编程语言,就有低级编程语言,从编程语言发展历史来说,可以划分为三个阶段:
机器语言:10010001111, 一些机器指令
汇编语言:mov ax,bx, 一些汇编指令;
高级语言: C , C++ , Java , Javascript , Python ;
计算机本身是不认识这些高级语言的,所以我们的代码最终还是需要被转换成机器指令:
认识浏览器的内核
不同的浏览器有不同的内核组成
Gecko:早期被Netscape和Mozila Firefox浏览器使用
Trident:微软开发,被IE4-IE11浏览器使用,但是Edge浏览器已经转向Blink;
Webkit:苹果基于KHTML开发,开源的,用于Safari, Google Chrome之前也在使用;
Blink: 是Webkit的一个分支, Google开发,目前应用于Google Chrome , Edge , Opera等;
浏览器渲染过程
1.浏览器先执行HTML形成DOM树,Css形成CSSOM,合成渲染树. 中间有一个Layout操作,该操作是根据浏览器窗口的大小去确定css布局.
2.解析html和css本篇就不细说了,接下来就是我们的第一个问题: Javascript代码由谁来执行呢?从这就引出了JavaScript引擎
认识Javascript引擎
我们可能在之前都知道要用js引擎来执行js代码,但为什么需要js引擎来执行可能就不太清楚了吧?
- 我们前面说过,高级的编程语言都是需要转成最终的机器指令来执行的
- 其实清楚编程语言知识的都知道,我们所说的这些语言最后都是由CPU来执行的,可CPU并不认识高级语言
- 但是CPU只认识自己的指令集,也就是机器语言,才能被CPU所执行
- 所以我们需要js引擎帮助我们将js代码翻译成CPU指令来执行
常见的Js引擎有哪些?
- SpiderMonkey:第一款Javascript引擎,由Brendan Eich开发(js作者)
- Chakra:微软开发,用于IT浏览器
- JavascriptCore:WebKit中的js引擎,Apple公司开发
- V8:Google开发的强大js引擎,也帮助Chrome从众多浏览器中脱颖而出
浏览器内核和js引擎的关系
Webkit:
WebCore: 负责HTML解析,布局,渲染等等相关工作
JavaScriptCore: 解析,执行Javascript代码
小程序中编写的Javascript代码就是被JSCore执行的;另外一个强大的Javascript引擎就是V8引擎
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执行js代码的流程图:
解析:
- Blink将js代码交给V8引擎,Stream获取到源码并且进行编码转换;
- Scanner会进行词法分析,词法分析会将代码转换成tokens;
- 接下来tokens会被转换成AST树,经过Parser和PreParser: Parser就是直接将tokens转成AST树架构,PreParser称之为预解析(因为并不是所有的js代码,在一开始时就会被执行,那么对所有的js代码进行解析,必然会影响网页的运行效率,所以V8引擎就实现了Lazy Parsing(延迟解析)方案,它的作用是将不必要的函数进行预解析,也就是只解析暂时需要的内容,而对函数的全局解析是在函数被调用时才会进行)
- Ignition会将AST转换为ByteCode(字节码),如果函数只调用一次,Ignition会解释执行ByteCode
- TurboFan是一个编译器,可以将字节码编译为CPU可以直接执行的机器码,如果一个函数被多次调用,那么就会被标记为热点函数,那么经过TurboFan转换成优化的机器码,提高代码的执行性能;机器码实际上也会被还原为ByteCode,这是因为如果后续执行函数的过程中,类型发生的变化,之前优化的机器码并不能正确的处理运算,就会逆向的转换成字节码。
function sum(num1,num2){
return num1 + num2
}
sum(20,20)
sum(30,30)
sum("aaa","bbb")
由于转换了数据类型,之前优化的机器码并不能正确的处理运算,就会逆向的转换成字节码
ts规定了数据的类型,所以就会减少了平台机器码由于类型改变不能正常操作而导致重新转换成字节码的情况
到此本篇就完结啦~,本篇只是简单介绍了v8引擎执行js的流程,各流程的详情原理咱们下篇见。关注小编不迷路。